ZQuest Classic Coverage Report


Directory: src/
File: src/zq/zq_tiles.cpp
Date: 2024-06-03 19:33:09
Exec Total Coverage
Lines: 93 7626 1.2%
Functions: 1 194 0.5%
Branches: 9 6345 0.1%

Line Branch Exec Source
1 #include <cstring>
2 #include <cmath>
3
4 #include "base/qrs.h"
5 #include "base/dmap.h"
6 #include "base/cpool.h"
7 #include "base/autocombo.h"
8 #include "base/packfile.h"
9 #include "base/gui.h"
10 #include "base/combo.h"
11 #include "base/msgstr.h"
12 #include "base/zdefs.h"
13 #include "zq/zquestdat.h"
14 #include "zq/zq_tiles.h"
15 #include "zq/zquest.h"
16 #include "tiles.h"
17 #include "zq/zq_misc.h"
18 #include "zq/zq_class.h"
19 #include "base/zsys.h"
20 #include "base/colors.h"
21 #include "qst.h"
22 #include "gui/jwin.h"
23 #include <base/new_menu.h>
24 #include "base/jwinfsel.h"
25 #include "zc/zc_custom.h"
26 #include "zq/questReport.h"
27 #include "dialog/info.h"
28 #include "dialog/scaletile.h"
29 #include "dialog/rotatetile.h"
30 #include "dialog/alert.h"
31 #include "drawing.h"
32 #include "colorname.h"
33 #include "zq/render.h"
34 #include "zinfo.h"
35 #include <fmt/format.h>
36 #include "zq/moveinfo.h"
37 using std::set;
38
39 extern zcmodule moduledata;
40
41 #ifdef _MSC_VER
42 #define stricmp _stricmp
43 #endif
44
45 #define HIDE_USED (show_only_unused_tiles&1)
46 #define HIDE_UNUSED (show_only_unused_tiles&2)
47 #define HIDE_BLANK (show_only_unused_tiles&4)
48 #define HIDE_8BIT_MARKER (show_only_unused_tiles&8)
49
50 extern void large_dialog(DIALOG *d);
51 static void massRecolorReset4Bit();
52 static void massRecolorReset8Bit();
53 static bool massRecolorSetup(int32_t cset);
54 static void massRecolorApply(int32_t tile);
55 extern int32_t last_droplist_sel;
56 extern int32_t TilePgCursorCol, CmbPgCursorCol;
57
58 int32_t ex=0;
59 int32_t nextcombo_fake_click=0;
60 int32_t invcol=0;
61 int32_t tthighlight = 1;
62 int32_t showcolortip = 1;
63 int32_t show_quartgrid = 0, hide_grid = 0;
64
65 tiledata *newundotilebuf;
66 std::vector<newcombo> undocombobuf;
67
68 BITMAP *selection_pattern;
69 byte selection_grid[18][18];
70 byte selection_anchor=0;
71
72 enum {selection_mode_normal, selection_mode_add, selection_mode_subtract, selection_mode_exclude};
73 BITMAP *selecting_pattern;
74 int32_t selecting_x1, selecting_x2, selecting_y1, selecting_y2;
75
76 extern int32_t bidcomboscripts_cnt;
77 extern script_struct bidcomboscripts[NUMSCRIPTSCOMBODATA];
78
79 BITMAP *intersection_pattern;
80
81 byte relational_template[48][4]=
82 {
83 { 0, 0, 0, 0 },
84 { 0, 1, 0, 0 },
85 { 1, 0, 0, 0 },
86 { 1, 1, 0, 0 },
87 { 0, 0, 1, 0 },
88 { 0, 1, 1, 0 },
89 { 1, 0, 1, 0 },
90 { 1, 1, 1, 0 },
91 { 0, 0, 0, 1 },
92 { 0, 1, 0, 1 },
93 { 1, 0, 0, 1 },
94 { 1, 1, 0, 1 },
95 { 0, 0, 1, 1 },
96 { 0, 1, 1, 1 },
97 { 1, 0, 1, 1 },
98 { 1, 1, 1, 1 },
99 { 0, 2, 0, 2 },
100 { 1, 2, 0, 2 },
101 { 0, 2, 1, 2 },
102 { 1, 2, 1, 2 },
103 { 3, 3, 0, 0 },
104 { 3, 3, 1, 0 },
105 { 3, 3, 0, 1 },
106 { 3, 3, 1, 1 },
107 { 3, 4, 0, 2 },
108 { 3, 4, 1, 2 },
109 { 2, 0, 2, 0 },
110 { 2, 1, 2, 0 },
111 { 2, 0, 2, 1 },
112 { 2, 1, 2, 1 },
113 { 2, 2, 2, 2 },
114 { 4, 3, 2, 0 },
115 { 4, 3, 2, 1 },
116 { 4, 4, 2, 2 },
117 { 0, 0, 3, 3 },
118 { 0, 1, 3, 3 },
119 { 1, 0, 3, 3 },
120 { 1, 1, 3, 3 },
121 { 0, 2, 3, 4 },
122 { 1, 2, 3, 4 },
123 { 3, 3, 3, 3 },
124 { 3, 4, 3, 4 },
125 { 2, 0, 4, 3 },
126 { 2, 1, 4, 3 },
127 { 2, 2, 4, 4 },
128 { 4, 3, 4, 3 },
129 { 4, 4, 4, 4 },
130 { 5, 5, 5, 5 }
131 };
132
133 byte dungeon_carving_template[96][4]=
134 {
135 { 0, 0, 0, 0 },
136 { 0, 1, 0, 0 },
137 { 1, 0, 0, 0 },
138 { 1, 1, 0, 0 },
139 { 0, 0, 1, 0 },
140 { 0, 1, 1, 0 },
141 { 1, 0, 1, 0 },
142 { 1, 1, 1, 0 },
143 { 0, 0, 0, 1 },
144 { 0, 1, 0, 1 },
145 { 1, 0, 0, 1 },
146 { 1, 1, 0, 1 },
147 { 0, 0, 1, 1 },
148 { 0, 1, 1, 1 },
149 { 1, 0, 1, 1 },
150 { 1, 1, 1, 1 },
151 { 0, 2, 0, 2 },
152 { 1, 2, 0, 2 },
153 { 0, 2, 1, 2 },
154 { 1, 2, 1, 2 },
155 { 3, 3, 0, 0 },
156 { 3, 3, 1, 0 },
157 { 3, 3, 0, 1 },
158 { 3, 3, 1, 1 },
159 { 3, 4, 0, 2 },
160 { 3, 4, 1, 2 },
161 { 2, 0, 2, 0 },
162 { 2, 1, 2, 0 },
163 { 2, 0, 2, 1 },
164 { 2, 1, 2, 1 },
165 { 2, 2, 2, 2 },
166 { 4, 3, 2, 0 },
167 { 4, 3, 2, 1 },
168 { 4, 4, 2, 2 },
169 { 0, 0, 3, 3 },
170 { 0, 1, 3, 3 },
171 { 1, 0, 3, 3 },
172 { 1, 1, 3, 3 },
173 { 0, 2, 3, 4 },
174 { 1, 2, 3, 4 },
175 { 3, 3, 3, 3 },
176 { 3, 4, 3, 4 },
177 { 2, 0, 4, 3 },
178 { 2, 1, 4, 3 },
179 { 2, 2, 4, 4 },
180 { 4, 3, 4, 3 },
181 { 4, 4, 4, 4 },
182 { 5, 5, 5, 5 },
183
184 { 5, 5, 5, 5 },
185 { 6, 6, 6, 6 },
186 { 7, 7, 7, 7 },
187 { 7, 6, 7, 6 },
188 { 8, 8, 8, 8 },
189 { 16, 6, 8, 15 },
190 { 7, 7, 8, 8 },
191 { 7, 6, 8, 15 },
192 { 9, 9, 9, 9 },
193 { 6, 6, 9, 9 },
194 { 7, 17, 14, 9 },
195 { 7, 6, 14, 9 },
196 { 8, 9, 8, 9 },
197 { 16, 6, 8, 9 },
198 { 7, 17, 8, 9 },
199 { 7, 6, 8, 9 },
200 { 10, 10, 10, 10 },
201 { 7, 10, 14, 10 },
202 { 16, 10, 8, 10 },
203 { 7, 10, 8, 10 },
204 { 11, 11, 11, 11 },
205 { 11, 11, 8, 15 },
206 { 11, 11, 14, 9 },
207 { 11, 11, 8, 9 },
208 { 14, 14, 14, 14 },
209 { 14, 14, 8, 14 },
210 { 12, 12, 12, 12 },
211 { 12, 6, 12, 15 },
212 { 12, 17, 12, 9 },
213 { 12, 6, 12, 9 },
214 { 12, 10, 12, 10 },
215 { 15, 15, 15, 15 },
216 { 15, 15, 15, 9 },
217 { 15, 14, 12, 10 },
218 { 13, 13, 13, 13 },
219 { 16, 6, 13, 13 },
220 { 7, 17, 13, 13 },
221 { 7, 6, 13, 13 },
222 { 16, 16, 16, 16 },
223 { 7, 16, 16, 16 },
224 { 11, 11, 13, 13 },
225 { 11, 14, 13, 16 },
226 { 17, 17, 17, 17 },
227 { 17, 6, 17, 17 },
228 { 12, 10, 17, 16 },
229 { 15, 11, 17, 13 },
230 { 15, 14, 17, 16 },
231 { 18, 18, 18, 18 }
232 };
233
234 struct tile_move_data
235 {
236 int32_t copies;
237 int32_t dest_first;
238 int32_t dest_last;
239 int32_t src_first;
240 int32_t src_last;
241 int32_t dest_top;
242 int32_t dest_bottom;
243 int32_t src_top;
244 int32_t src_bottom;
245 int32_t src_left, src_right;
246 int32_t src_width, src_height;
247 int32_t dest_left, dest_right;
248 int32_t dest_width, dest_height;
249 int32_t rows, cols;
250 bool rect, move;
251
252 tile_move_data()
253 {
254 copies = dest_first = dest_last = src_first = src_last = dest_top =
255 dest_bottom = src_top = src_bottom = src_left = src_right =
256 src_width = src_height = dest_left = dest_right = dest_width =
257 dest_height = rows = cols = 0;
258 rect = move = false;
259 }
260
261 tile_move_data(tile_move_data const& other)
262 {
263 copy(other);
264 }
265
266 tile_move_data& operator=(tile_move_data const& other)
267 {
268 copy(other);
269 return *this;
270 }
271
272 void copy(tile_move_data const& other)
273 {
274 copies = other.copies;
275 dest_first = other.dest_first;
276 dest_last = other.dest_last;
277 src_first = other.src_first;
278 src_last = other.src_last;
279 dest_top = other.dest_top;
280 dest_bottom = other.dest_bottom;
281 src_top = other.src_top;
282 src_bottom = other.src_bottom;
283 src_left = other.src_left;
284 src_right = other.src_right;
285 src_width = other.src_width;
286 src_height = other.src_height;
287 dest_left = other.dest_left;
288 dest_right = other.dest_right;
289 dest_width = other.dest_width;
290 dest_height = other.dest_height;
291 rows = other.rows;
292 cols = other.cols;
293 rect = other.rect;
294 move = other.move;
295 }
296
297 void flip()
298 {
299 zc_swap(src_first, dest_first);
300 zc_swap(src_last, dest_last);
301 zc_swap(src_top, dest_top);
302 zc_swap(src_bottom, dest_bottom);
303 zc_swap(src_left, dest_left);
304 zc_swap(src_right, dest_right);
305 zc_swap(src_width, dest_width);
306 zc_swap(src_height, dest_height);
307 }
308 };
309 bool do_movetile_united(tile_move_data const& tmd);
310
311 struct combo_move_data
312 {
313 int32_t tile, tile2, copy1, copycnt;
314 combo_move_data() : tile(0), tile2(0), copy1(0), copycnt(0){}
315 combo_move_data(combo_move_data const& other)
316 {
317 copy(other);
318 }
319 combo_move_data& operator=(combo_move_data const& other)
320 {
321 copy(other);
322 return *this;
323 }
324 void copy(combo_move_data const& other)
325 {
326 tile = other.tile;
327 tile2 = other.tile2;
328 copy1 = other.copy1;
329 copycnt = other.copycnt;
330 }
331
332 void flip()
333 {
334 int32_t tcnt = tile2-tile+1;
335 int32_t cpy2 = copy1+copycnt-1;
336 zc_swap(tile,copy1);
337 tile2 = cpy2;
338 copycnt = tcnt;
339 }
340 };
341
342 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing = false);
343 static optional<ComboMoveUndo> last_combo_move_list;
344 static optional<TileMoveUndo> last_tile_move_list;
345
346 int refl_flags = 0;
347 enum
348 {
349 REFL_90CW, REFL_HFLIP,
350 REFL_90CCW, REFL_VFLIP,
351 REFL_180, REFL_DBLFLIP,
352 REFL_MAX
353 };
354 const char *reflbtn_names[] =
355 {
356 "90 CW", "HFlip",
357 "90 CCW", "VFlip",
358 "180 Rot", "Diag Flip"
359 };
360 int bgmode = 0, xmode = 0;
361 const char *bgmodebtn_names[] =
362 {
363 "BG Color 0", "BG Trans."
364 };
365 const char *xmodebtn_names[] =
366 {
367 "X", "No X"
368 };
369 enum
370 {
371 XMODE_X, XMODE_NOX,
372 XMODE_MAX
373 };
374 enum
375 {
376 BGMODE_0, BGMODE_TRANSP,
377 BGMODE_MAX
378 };
379
380 /*********************************/
381 /***** Tiles & Combos ******/
382 /*********************************/
383
384 void merge_tiles(int32_t dest_tile, int32_t src_quarter1, int32_t src_quarter2, int32_t src_quarter3, int32_t src_quarter4)
385 {
386 int32_t size=tilesize(newtilebuf[dest_tile].format)>>4;
387 int32_t size2=size>>1;
388
389 if(newtilebuf[dest_tile].data==NULL)
390 {
391 reset_tile(newtilebuf, dest_tile, newtilebuf[src_quarter1>>2].format);
392 }
393
394 int32_t i=0;
395
396 if((dest_tile<<2)+i!=src_quarter1)
397 {
398 for(int32_t j=0; j<8; ++j)
399 {
400 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter1>>2].data[((j+((src_quarter1&2)<<2))*size)+((src_quarter1&1)*size2)]), size2);
401 }
402 }
403
404 i=1;
405
406 if((dest_tile<<2)+i!=src_quarter2)
407 {
408 for(int32_t j=0; j<8; ++j)
409 {
410 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter2>>2].data[((j+((src_quarter2&2)<<2))*size)+((src_quarter2&1)*size2)]), size2);
411 }
412 }
413
414 i=2;
415
416 if((dest_tile<<2)+i!=src_quarter3)
417 {
418 for(int32_t j=0; j<8; ++j)
419 {
420 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter3>>2].data[((j+((src_quarter3&2)<<2))*size)+((src_quarter3&1)*size2)]), size2);
421 }
422 }
423
424 i=3;
425
426 if((dest_tile<<2)+i!=src_quarter4)
427 {
428 for(int32_t j=0; j<8; ++j)
429 {
430 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter4>>2].data[((j+((src_quarter4&2)<<2))*size)+((src_quarter4&1)*size2)]), size2);
431 }
432 }
433 }
434
435 static void make_combos(int32_t startTile, int32_t endTile, int32_t cs)
436 {
437 al_trace("inside make_combos()\n");
438 int32_t startCombo=0;
439
440 if(!select_combo_2(startCombo,cs))
441 return;
442
443 int32_t temp=combobuf[startCombo].o_tile;
444 combobuf[startCombo].set_tile(startTile);
445
446 if(!edit_combo(startCombo, false, cs))
447 {
448 combobuf[startCombo].set_tile(temp);
449 return;
450 }
451
452 go_combos();
453
454 for(int32_t i=0; i<=endTile-startTile; i++)
455 {
456 combobuf[startCombo+i]=combobuf[startCombo];
457 combobuf[startCombo+i].set_tile(startTile+i);
458 }
459
460 setup_combo_animations();
461 setup_combo_animations2();
462 }
463
464 static void make_combos_rect(int32_t top, int32_t left, int32_t numRows, int32_t numCols, int32_t cs)
465 {
466 //al_trace("inside make_combos_rect()\n");
467 int32_t startCombo=0;
468
469 if(!select_combo_2(startCombo, cs))
470 return;
471
472 int32_t startTile=top*TILES_PER_ROW+left;
473 int32_t temp=combobuf[startCombo].o_tile;
474 combobuf[startCombo].set_tile(startTile);
475
476 if(!edit_combo(startCombo, false, cs))
477 {
478 al_trace("make_combos_rect() early return\n");
479 combobuf[startCombo].set_tile(temp);
480 return;
481 }
482
483 bool smartWrap=false;
484 if(numCols!=4 && numRows>1)
485 {
486 char buf[64];
487 if(numCols<4)
488 sprintf(buf, "Limit to %d column%s?", numCols, numCols==1 ? "" : "s");
489 else
490 sprintf(buf, "Fit to 4 columns?"); // Meh, whatever.
491 int32_t ret=jwin_alert("Wrapping", buf, NULL, NULL, "&Yes", "&No", 'y', 'n', get_zc_font(font_lfont));
492 if(ret==1)
493 smartWrap=true;
494 }
495
496 go_combos();
497
498 int32_t combo=startCombo-1;
499 for(int32_t row=0; row<numRows; row++)
500 {
501 for(int32_t col=0; col<numCols; col++)
502 {
503 int32_t tile=startTile+row*TILES_PER_ROW+col;
504 if(smartWrap)
505 // Add 4 per row, and another numRows*4 for every 4 columns
506 // (col&0xFC==col/4*4), and then the column %4
507 combo=startCombo+4*row+(col&0xFC)*numRows+col%4;
508 else
509 combo++;
510
511 combobuf[combo]=combobuf[startCombo];
512 combobuf[combo].set_tile(tile);
513 }
514 }
515
516 setup_combo_animations();
517 setup_combo_animations2();
518 }
519
520 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t c);
521
522 static bool nogotiles = false;
523 static bool nogocombos = false;
524
525 void go_tiles()
526 {
527 if(nogotiles) return;
528 last_tile_move_list = nullopt;
529 for(int32_t i=0; i<NEWMAXTILES; ++i)
530 {
531 newundotilebuf[i].format=newtilebuf[i].format;
532
533 if(newundotilebuf[i].data!=NULL)
534 {
535 free(newundotilebuf[i].data);
536 }
537
538 newundotilebuf[i].data=(byte *)malloc(tilesize(newundotilebuf[i].format));
539
540 if(newundotilebuf[i].data==NULL)
541 {
542 Z_error_fatal("Unable to initialize undo tile #%ld.\n", i);
543 }
544
545 memcpy(newundotilebuf[i].data,newtilebuf[i].data,tilesize(newundotilebuf[i].format));
546 }
547 }
548
549 void go_slide_tiles(int32_t columns, int32_t rows, int32_t top, int32_t left)
550 {
551 for(int32_t c=0; c<columns; c++)
552 {
553 for(int32_t r=0; r<rows; r++)
554 {
555 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
556 newundotilebuf[t].format=newtilebuf[t].format;
557
558 if(newundotilebuf[t].data!=NULL)
559 {
560 free(newundotilebuf[t].data);
561 }
562
563 newundotilebuf[t].data=(byte *)malloc(tilesize(newundotilebuf[t].format));
564
565 if(newundotilebuf[t].data==NULL)
566 {
567 Z_error_fatal("Unable to initialize undo tile #%ld.\n", t);
568 }
569
570 memcpy(newundotilebuf[t].data,newtilebuf[t].data,tilesize(newundotilebuf[t].format));
571 }
572 }
573 }
574
575 void comeback_tiles()
576 {
577 if(last_tile_move_list)
578 {
579 last_tile_move_list->undo();
580 last_tile_move_list = nullopt;
581 }
582 for(dword i=0; i<NEWMAXTILES; ++i)
583 {
584 if(newtilebuf[i].format != newundotilebuf[i].format || !newtilebuf[i].data)
585 {
586 newtilebuf[i].format = newundotilebuf[i].format;
587
588 if(newtilebuf[i].data!=NULL)
589 free(newtilebuf[i].data);
590 newtilebuf[i].data=(byte *)malloc(tilesize(newtilebuf[i].format));
591 if(newtilebuf[i].data==NULL)
592 Z_error_fatal("Unable to initialize tile #%ld.\n", i);
593 }
594
595 memcpy(newtilebuf[i].data,newundotilebuf[i].data,tilesize(newtilebuf[i].format));
596 }
597
598 register_blank_tiles();
599 register_used_tiles();
600 }
601
602 void go_combos()
603 {
604 if(nogocombos) return;
605 last_combo_move_list = nullopt;
606
607 undocombobuf = combobuf;
608 }
609
610 void comeback_combos()
611 {
612 if(last_combo_move_list)
613 {
614 last_combo_move_list->undo();
615 last_combo_move_list = nullopt;
616 }
617
618 combobuf = undocombobuf;
619 }
620
621 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t s)
622 {
623 line(dest,x,y,x+s,y+s,c);
624 line(dest,x+s,y,x,y+s,c);
625 }
626 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t w, int32_t h)
627 {
628 line(dest,x,y,x+w,y+h,c);
629 line(dest,x+w,y,x,y+h,c);
630 }
631
632 enum {gm_light, gm_dark, gm_max};
633 int32_t gridmode=gm_light;
634
635 bool has_selection()
636 {
637 for(int32_t i=1; i<17; ++i)
638 {
639 for(int32_t j=1; j<17; ++j)
640 {
641 if(selection_grid[i][j])
642 {
643 return true;
644 }
645 }
646 }
647
648 return false;
649 }
650
651 void draw_selection_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
652 {
653 drawing_mode(DRAW_MODE_COPY_PATTERN, selection_pattern, selection_anchor>>3, 0);
654
655 for(int32_t i=1; i<18; ++i)
656 {
657 for(int32_t j=1; j<18; ++j)
658 {
659 // zoomtile16(screen2,tile,79,31,cs,flip,8);
660 if(selection_grid[i-1][j]!=selection_grid[i][j])
661 {
662 _allegro_vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
663 }
664
665 if(selection_grid[i][j-1]!=selection_grid[i][j])
666 {
667 _allegro_hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
668 }
669 }
670 }
671
672 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
673 // selection_anchor=(selection_anchor+1)%64;
674 }
675
676 bool is_selecting()
677 {
678 return (selecting_x1>-1&&selecting_x2>-1&&selecting_y1>-1&&selecting_y2>-1);
679 }
680
681 void draw_selecting_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
682 {
683 int32_t x1=zc_min(selecting_x1,selecting_x2);
684 int32_t x2=zc_max(selecting_x1,selecting_x2);
685 int32_t y1=zc_min(selecting_y1,selecting_y2);
686 int32_t y2=zc_max(selecting_y1,selecting_y2);
687
688 // rect(dest, x+(x1*scale2), y+(y1*scale2), x+((x2+1)*scale2), y+((y2+1)*scale2), 255);
689 for(int32_t i=1; i<18; ++i)
690 {
691 for(int32_t j=1; j<18; ++j)
692 {
693 drawing_mode(DRAW_MODE_COPY_PATTERN, selecting_pattern, selection_anchor>>3, 0);
694
695 if(((j>=y1+1)&&(j<=y2+1))&&((i==x1+1)||(i==x2+2)))
696 {
697 if(selection_grid[i-1][j]!=selection_grid[i][j])
698 {
699 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
700 }
701
702 _allegro_vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
703 }
704
705 if(((i>=x1+1)&&(i<=x2+1))&&((j==y1+1)||(j==y2+2)))
706 {
707 if(selection_grid[i][j-1]!=selection_grid[i][j])
708 {
709 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
710 }
711
712 _allegro_hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
713 }
714 }
715 }
716
717 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
718 // selection_anchor=(selection_anchor+1)%64;
719 }
720
721 void unfloat_selection();
722 bool floating_sel = false;
723 byte floatsel[256];
724 byte undofloatsel[256];
725 bool undo_is_floatsel = false;
726
727
728 void add_color_to_selection(int32_t color)
729 {
730 unfloat_selection();
731 for(int32_t i=1; i<17; ++i)
732 {
733 for(int32_t j=1; j<17; ++j)
734 {
735 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
736 {
737 selection_grid[i][j]=1;
738 }
739 }
740 }
741 }
742
743 void remove_color_from_selection(int32_t color)
744 {
745 unfloat_selection();
746 for(int32_t i=1; i<17; ++i)
747 {
748 for(int32_t j=1; j<17; ++j)
749 {
750 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
751 {
752 selection_grid[i][j]=0;
753 }
754 }
755 }
756 }
757
758 void intersect_color_with_selection(int32_t color)
759 {
760 unfloat_selection();
761 for(int32_t i=1; i<17; ++i)
762 {
763 for(int32_t j=1; j<17; ++j)
764 {
765 if((unpackbuf[((j-1)<<4)+(i-1)]==color)&&(selection_grid[i][j]==1))
766 {
767 selection_grid[i][j]=1;
768 }
769 else
770 {
771 selection_grid[i][j]=0;
772 }
773 }
774 }
775 }
776
777 bool is_in_selection(int32_t x, int32_t y)
778 {
779 x %= 16; y %= 16;
780 if(x < 0) x = (16 - abs(x));
781 if(y < 0) y = (16 - abs(y));
782 return (!has_selection()||(selection_grid[x+1][y+1]!=0));
783 }
784
785 void zoomtile16(BITMAP *dest,int32_t tile,int32_t x,int32_t y,int32_t cset,int32_t flip,int32_t m)
786 {
787 // rectfill(dest,x,y,x+(16*m),y+(16*m),gridmode==gm_light?jwin_pal[jcMEDLT]:jwin_pal[jcDARK]);
788 int gridcol = gridmode==gm_light?vc(7):vc(8);
789
790 cset <<= 4;
791 if(newtilebuf[tile].format>tf4Bit)
792 cset=0;
793
794 int g = hide_grid ? 1 : 0;
795 byte transp_col = (bgmode == BGMODE_TRANSP ? jwin_pal[jcBOX] : 0+cset);
796 rectfill(dest,x,y,x+(16*m)+g,y+(16*m)+g,transp_col);
797
798 unpack_tile(newtilebuf, tile, 0, false);
799 byte *si = unpackbuf;
800 for(int32_t cy=0; cy<16; cy++)
801 {
802 for(int32_t cx=0; cx<16; cx++)
803 {
804 byte col = (floating_sel && floatsel[cx+(cy<<4)]) ? floatsel[cx+(cy<<4)] : *si;
805 int32_t dx = ((flip&1)?15-cx:cx)*m;
806 int32_t dy = ((flip&2)?15-cy:cy)*m;
807 if(col)
808 rectfill(dest,x+dx,y+dy,x+dx+m-1,y+dy+m-1,col+cset);
809
810 if(!col && xmode == XMODE_X)
811 little_x(dest,x+dx+m/4,y+dy+m/4,invcol,m/2);
812
813 ++si;
814 }
815 }
816
817 if(!hide_grid)
818 {
819 for(int cx = 0; cx <= 16; ++cx)
820 _allegro_vline(dest,x+(cx*m),y,y+(16*m)-1,gridcol);
821 for(int cy = 0; cy <= 16; ++cy)
822 _allegro_hline(dest,x,y+(cy*m),x+(16*m)-1,gridcol);
823 }
824
825 if(show_quartgrid)
826 {
827 int offs = (8*m);
828 const int RAD = 3;
829 rectfill(dest,x+offs-RAD,y,x+offs+RAD,y+(16*m),gridcol);
830 rectfill(dest,x,y+offs-RAD,x+(16*m),y+offs+RAD,gridcol);
831 }
832
833 if(has_selection()||is_selecting())
834 {
835 selection_anchor=(selection_anchor+1)%64;
836
837 if(has_selection()||is_selecting())
838 draw_selection_outline(dest, x, y, m);
839
840 if(is_selecting())
841 draw_selecting_outline(dest, x, y, m);
842 }
843 }
844
845 void draw_text_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,int32_t flags,bool jwin)
846 {
847 if(!jwin)
848 {
849 if(flags&D_SELECTED)
850 {
851 zc_swap(fg,bg);
852 }
853
854 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
855 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
856 rect(dest,x,y,x+w-2,y+h-2,fg);
857 textout_centre_ex(dest,font,text,(x+x+w)>>1,((y+y+h)>>1)-4,fg,-1);
858 }
859 else
860 {
861 jwin_draw_text_button(dest, x, y, w, h, text, flags, true);
862 }
863 }
864
865 void draw_icon_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,int icon,int32_t bg,int32_t fg,int32_t flags,bool jwin)
866 {
867 if(!jwin)
868 {
869 if(flags&D_SELECTED)
870 {
871 zc_swap(fg,bg);
872 }
873
874 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
875 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
876 rect(dest,x,y,x+w-2,y+h-2,fg);
877 jwin_draw_icon(dest,x+w/2,y+h/2,fg,icon,icon_proportion(icon,w,h),true);
878 }
879 else
880 {
881 jwin_draw_icon_button(dest, x, y, w, h, icon, flags, true);
882 }
883 }
884
885 void draw_layer_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t flags)
886 {
887 if(flags&D_SELECTED)
888 {
889 rect(dest, x, y, x+w-1, y+h-1, jwin_pal[jcDARK]);
890 ++x;
891 ++y;
892 --w;
893 --h;
894 }
895 rectfill(dest,x+1,y+1,x+w-3,y+h-3,jwin_pal[(flags&D_SELECTED ? jcMEDDARK : jcBOX)]);
896 jwin_draw_frame(dest, x, y, w, h, (flags&D_SELECTED ? FR_DARK : FR_BOX));
897
898 //Forcibly fit the text within the button
899 char buf[512] = {0};
900 strcpy(buf, text);
901
902 bool dis = (flags&D_DISABLED);
903 auto hei = text_height(font);
904 auto len = text_length(font,buf);
905 auto borderwid = 8;
906 if(len > w - borderwid + (dis ? 1 : 0))
907 {
908 auto ind = strlen(buf) - 1;
909 auto dotcount = 0;
910 while(len > w - borderwid + (dis ? 1 : 0))
911 {
912 if(dotcount >= 2)
913 buf[ind+2] = 0;
914 else ++dotcount;
915 buf[ind--] = '.';
916 len = text_length(font,buf);
917 }
918 }
919 if(dis)
920 {
921 ++len; ++hei;
922 }
923 BITMAP* tmp = create_bitmap_ex(8,len,hei);
924 clear_bitmap(tmp);
925 if(dis)
926 {
927 textout_ex(tmp,font,buf,1,1,jwin_pal[jcLIGHT],-1);
928 textout_ex(tmp,font,buf,0,0,jwin_pal[jcDISABLED_FG],-1);
929 }
930 else
931 textout_ex(tmp,font,buf,0,0,jwin_pal[jcBOXFG],-1);
932 auto tx = x+((w-len)/2);
933 auto ty = y+((h-hei)/2);
934 if(len > w-borderwid)
935 {
936 tx = x+borderwid/2;
937 len = w-borderwid;
938 }
939 if(hei > h-borderwid)
940 {
941 ty = y+borderwid/2;
942 hei = h-borderwid;
943 }
944 masked_blit(tmp,dest, 0,0, tx,ty, len, hei);
945 destroy_bitmap(tmp);
946 }
947
948 bool do_layer_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text, int32_t flags, bool toggleflag)
949 {
950 bool over=false;
951
952 while(gui_mouse_b())
953 {
954 //vsync();
955 if(mouse_in_rect(x,y,w,h))
956 {
957 if(!over)
958 {
959 vsync();
960 draw_layer_button(screen, x, y, w, h, text, flags^D_SELECTED);
961 over=true;
962
963 update_hw_screen();
964 }
965 }
966 else
967 {
968 if(over)
969 {
970 vsync();
971 draw_layer_button(screen, x, y, w, h, text, flags);
972 over=false;
973
974 update_hw_screen();
975 }
976 }
977 rest(1);
978 }
979
980 if(over)
981 {
982 vsync();
983 draw_layer_button(screen, x, y, w, h, text, toggleflag ? flags^D_SELECTED : flags);
984
985 update_hw_screen();
986 }
987
988 return over;
989 }
990
991 bool do_text_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,bool jwin, bool sel)
992 {
993 bool over=false;
994
995 while(gui_mouse_b())
996 {
997 custom_vsync();
998
999 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1000 {
1001 if(!over)
1002 {
1003 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1004 over=true;
1005 }
1006 }
1007 else
1008 {
1009 if(over)
1010 {
1011 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?D_SELECTED:0,jwin);
1012 over=false;
1013 }
1014 }
1015 }
1016
1017 if(over)
1018 {
1019 custom_vsync();
1020 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1021 }
1022
1023 return over;
1024 }
1025
1026 void draw_graphics_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,int32_t flags,bool jwin,bool overlay)
1027 {
1028 if(!jwin)
1029 {
1030 if(flags&D_SELECTED)
1031 {
1032 zc_swap(fg,bg);
1033 }
1034
1035 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
1036 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
1037 rect(dest,x,y,x+w-2,y+h-2,fg);
1038 int32_t g = (flags & D_SELECTED) ? 1 : 0;
1039
1040 if(overlay)
1041 {
1042 masked_blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1043 }
1044 else
1045 {
1046 blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1047 }
1048 }
1049 else
1050 {
1051 jwin_draw_graphics_button(dest, x, y, w, h, bmp, bmp2, flags, false, overlay);
1052 }
1053 }
1054
1055 bool do_graphics_button(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1056 {
1057 bool over=false;
1058
1059 while(gui_mouse_b())
1060 {
1061 custom_vsync();
1062
1063 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1064 {
1065 if(!over)
1066 {
1067 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1068 over=true;
1069 }
1070 }
1071 else
1072 {
1073 if(over)
1074 {
1075 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1076 over=false;
1077 }
1078 }
1079 }
1080
1081 return over;
1082 }
1083
1084 bool do_graphics_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1085 {
1086 bool over=false;
1087
1088 while(gui_mouse_b())
1089 {
1090 custom_vsync();
1091
1092 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1093 {
1094 if(!over)
1095 {
1096 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1097 over=true;
1098 }
1099 }
1100 else
1101 {
1102 if(over)
1103 {
1104 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1105 over=false;
1106 }
1107 }
1108 }
1109
1110 if(over)
1111 {
1112 custom_vsync();
1113 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1114 }
1115
1116 return over;
1117 }
1118 // circle(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1119 // circlefill(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1120
1121 void draw_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg, int32_t value)
1122 {
1123 //these are here to bypass compiler warnings about unused arguments
1124 bg=bg;
1125 fg=fg;
1126
1127 int32_t r, center;
1128
1129 for(int32_t k=0; k<7; k++)
1130 {
1131 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1132 {
1133 // circle(dest, x+(k*25)+4, y+4, 4, fg);
1134 // circlefill(dest, x+(k*25)+4, y+4, 2, (value==k)?fg:bg);
1135 //*
1136 r = 9/2;
1137
1138 center = x+(k*25)+r;
1139 rectfill(dest, x+(k*25), y, x+(k*25)+9-1, y+9-1, jwin_pal[jcBOX]);
1140
1141 circlefill(dest, center, y+r, r, jwin_pal[jcLIGHT]);
1142 arc(dest, center, y+r, itofix(32), itofix(160), r, jwin_pal[jcMEDDARK]);
1143 circlefill(dest, center, y+r, r-1, jwin_pal[jcMEDLT]);
1144 arc(dest, center, y+r, itofix(32), itofix(160), r-1, jwin_pal[jcDARK]);
1145 circlefill(dest, center, y+r, r-2, jwin_pal[jcLIGHT]);
1146
1147 if(value==k)
1148 {
1149 circlefill(dest, center, y+r, r-3, jwin_pal[jcDARK]);
1150 }
1151
1152 //*/
1153 }
1154 }
1155 }
1156
1157 void do_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg,int32_t &value)
1158 {
1159 while(gui_mouse_b())
1160 {
1161 custom_vsync();
1162
1163 for(int32_t k=0; k<7; k++)
1164 {
1165 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1166 {
1167 //if on radio button
1168 if(isinRect(gui_mouse_x(),gui_mouse_y(),x+(k*25),y,x+(k*25)+8,y+8))
1169 {
1170 value=k;
1171 draw_layerradio(dest,x,y,bg,fg,value);
1172 refresh(rMENU);
1173 }
1174 }
1175 }
1176 }
1177 }
1178
1179 //*************** tile flood fill stuff **************
1180
1181 byte tf_c;
1182 byte tf_u;
1183
1184 void tile_floodfill_rec(int32_t x,int32_t y)
1185 {
1186 if(is_in_selection(x,y))
1187 {
1188 while(x>0 && (unpackbuf[(y<<4)+x-1] == tf_u))
1189 --x;
1190
1191 while(x<=15 && (unpackbuf[(y<<4)+x] == tf_u))
1192 {
1193 if(is_in_selection(x,y))
1194 {
1195 unpackbuf[(y<<4)+x] = tf_c;
1196 }
1197
1198 if(y>0 && (unpackbuf[((y-1)<<4)+x] == tf_u))
1199 tile_floodfill_rec(x,y-1);
1200
1201 if(y<15 && (unpackbuf[((y+1)<<4)+x] == tf_u))
1202 tile_floodfill_rec(x,y+1);
1203
1204 ++x;
1205 }
1206 }
1207 }
1208
1209 void tile_floodfill(int32_t tile,int32_t x,int32_t y,byte c)
1210 {
1211 if(is_in_selection(x,y))
1212 {
1213 if(floating_sel)
1214 {
1215 memcpy(unpackbuf, floatsel, 256);
1216 }
1217 else unpack_tile(newtilebuf, tile, 0, false);
1218 tf_c = c;
1219 tf_u = unpackbuf[(y<<4)+x];
1220
1221 if(tf_u != tf_c)
1222 tile_floodfill_rec(x,y);
1223 if(floating_sel)
1224 {
1225 memcpy(floatsel, unpackbuf, 256);
1226 }
1227 else pack_tile(newtilebuf,unpackbuf,tile);
1228 }
1229 }
1230
1231 //***************** tile editor stuff *****************
1232 9 size_and_pos ok_button(302,562,71,21);
1233 9 size_and_pos cancel_button(376,562,71,21);
1234 9 size_and_pos edit_button(550,562,86,21);
1235 9 size_and_pos hlcbox(742,392,16,16);
1236 9 size_and_pos hov_prev(742,338,50,50);
1237 9 size_and_pos cpalette_4(648,416,4,4,64,64);
1238 9 size_and_pos cpalette_8(648,416,16,14,16,18);
1239 9 size_and_pos fg_prev(648,316,50,50);
1240 9 size_and_pos bg_prev(648+30,316+30,50,50);
1241 9 size_and_pos zoomtile(124,32,16,16,32,32);
1242 9 size_and_pos prev_til_1(648,31,96,96);
1243 9 size_and_pos prev_til_2(752,31,96,96);
1244 9 size_and_pos prev_til_3(648,135,96,96);
1245 9 size_and_pos prev_til_4(752,135,96,96);
1246 9 size_and_pos status_info(648,308-(4*8),1,4,1,8);
1247 9 size_and_pos hover_info(742,338-(3*8),1,3,1,8);
1248 9 size_and_pos color_info(4,189,1,1,116,8);
1249 9 size_and_pos color_info_btn(24,189,96,21);
1250 9 size_and_pos tool_btns(22,29,2,4,39,39);
1251 9 size_and_pos x_btn(890,5,15,13);
1252 9 size_and_pos info_btn(872,5,15,13);
1253 9 size_and_pos hidegrid_cbox(124,552,16,16);
1254 9 size_and_pos quartgrid_cbox(124,572,16,16);
1255 9 size_and_pos reflbtn_grid(124,610,2,3,71,21);
1256 9 size_and_pos xmodebtn_grid(300,610,1,2,90,21);
1257 9 size_and_pos bgmodebtn_grid(390,610,1,2,90,21);
1258
1259 int32_t c1=1;
1260 int32_t c2=0;
1261 //int32_t bgc=dvc(4+5);
1262 //int32_t bgc=vc(1);
1263 //enum { t_pen, t_fill, t_recolor, t_eyedropper, t_move, t_select, t_wand, t_max };
1264 int32_t floating_tile = -1;
1265 int32_t tool = t_pen;
1266 int32_t old_tool = -1;
1267 int32_t tool_cur = -1;
1268 int32_t select_mode = 0;
1269 int32_t drawing=0;
1270
1271 bool qgrid_tool(int tool)
1272 {
1273 switch(tool)
1274 {
1275 case t_pen:
1276 case t_fill:
1277 case t_recolor:
1278 case t_wand:
1279 return true;
1280 }
1281 return false;
1282 }
1283
1284 void set_tool_sprite(int tool, int type)
1285 {
1286 int spr = ZQM_NORMAL;
1287 switch(tool)
1288 {
1289 case t_pen: spr = ZQM_SWORD; break;
1290 case t_fill: spr = ZQM_POTION; break;
1291 case t_recolor: spr = ZQM_WAND; break;
1292 case t_eyedropper: spr = ZQM_LENS; break;
1293 case t_move: spr = ZQM_GLOVE_OPEN+type; break;
1294 case t_select: spr = ZQM_HOOK_PLAIN+type; break;
1295 case t_wand: spr = ZQM_SEL_WAND_PLAIN+type; break;
1296 }
1297 MouseSprite::set(spr);
1298 }
1299 void update_tool_cursor()
1300 {
1301 // int32_t screen_xofs=(zq_screen_w-320)>>1;
1302 // int32_t screen_yofs=(zq_screen_h-240)>>1;
1303 // int32_t temp_mouse_x=gui_mouse_x()-screen_xofs;
1304 // int32_t temp_mouse_y=gui_mouse_y()-screen_yofs;
1305 int32_t temp_mouse_x=gui_mouse_x();
1306 int32_t temp_mouse_y=gui_mouse_y();
1307
1308 int32_t type=0;
1309
1310 if(has_selection())
1311 {
1312 switch(tool)
1313 {
1314 case t_select:
1315 case t_wand:
1316 type+=select_mode;
1317 break;
1318 }
1319 }
1320
1321 // if(isinRect(temp_mouse_x,temp_mouse_y,80,32,206,158)) //inside the zoomed tile window
1322 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
1323 {
1324 if(tool_cur==-1)
1325 set_tool_sprite(tool,type);
1326
1327 tool_cur=tool;
1328 }
1329 else if(tool_cur != -1)
1330 {
1331 MouseSprite::set(ZQM_NORMAL);
1332 tool_cur = -1;
1333 }
1334 }
1335
1336 void draw_edit_scr(int32_t tile,int32_t flip,int32_t cs,byte *oldtile, bool create_tbar)
1337 {
1338 PALETTE tpal;
1339 static BITMAP *tbar = create_bitmap_ex(8,zq_screen_w-6, 18);
1340 static BITMAP *preview_bmp = create_bitmap_ex(8, 64, 64);
1341 jwin_draw_win(screen2, 0, 0, zq_screen_w, zq_screen_h, FR_WIN);
1342
1343 if(!create_tbar)
1344 {
1345 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1346 }
1347 else
1348 {
1349 jwin_draw_titlebar(tbar, 0, 0, zq_screen_w-6, 18, "", true, true);
1350 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1351 }
1352
1353 textprintf_ex(screen2,get_zc_font(font_lfont),5,5,jwin_pal[jcTITLEFG],-1,"Tile Editor (%d)",tile);
1354
1355 clear_to_color(preview_bmp, 0);
1356
1357 zc_swap(oldtile,newtilebuf[tile].data); //Put oldtile in the tile buffer
1358 jwin_draw_win(screen2, prev_til_1.x-2,prev_til_1.y-2, prev_til_1.w+4, prev_til_1.h+4, FR_DEEP);
1359 puttile16(preview_bmp,tile,0,0,cs,flip);
1360 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_1.x, prev_til_1.y, prev_til_1.w, prev_til_1.h);
1361
1362 clear_to_color(preview_bmp, 0);
1363 jwin_draw_win(screen2, prev_til_2.x-2,prev_til_2.y-2, prev_til_2.w+4, prev_til_2.h+4, FR_DEEP);
1364 overtile16(preview_bmp,tile,0,0,cs,flip);
1365 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_2.x, prev_til_2.y, prev_til_2.w, prev_til_2.h);
1366 zc_swap(oldtile,newtilebuf[tile].data); //Swap the real tile back to the buffer
1367
1368 unpack_tile(newtilebuf, tile, 0, true);
1369 if(floating_sel)
1370 for(auto q = 0; q < 256; ++q)
1371 if(floatsel[q])
1372 unpackbuf[q] = floatsel[q];
1373 byte tmptile[256];
1374 byte *tmpptr = tmptile;
1375 zc_swap(tmpptr,newtilebuf[tile].data); //Put temp data in the tile buffer
1376 pack_tile(newtilebuf,unpackbuf,tile);
1377 clear_to_color(preview_bmp, 0);
1378
1379 jwin_draw_win(screen2, prev_til_3.x-2,prev_til_3.y-2, prev_til_3.w+4, prev_til_3.h+4, FR_DEEP);
1380 puttile16(preview_bmp,tile,0,0,cs,flip);
1381 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_3.x, prev_til_3.y, prev_til_3.w, prev_til_3.h);
1382
1383 clear_to_color(preview_bmp, 0);
1384 jwin_draw_win(screen2, prev_til_4.x-2,prev_til_4.y-2, prev_til_4.w+4, prev_til_4.h+4, FR_DEEP);
1385 overtile16(preview_bmp,tile,0,0,cs,flip);
1386 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_4.x, prev_til_4.y, prev_til_4.w, prev_til_4.h);
1387
1388 //Color info
1389 {
1390 auto fh = color_info.yscale = text_height(font);
1391 int y = color_info.y;
1392 int rx = color_info.x+color_info.xscale;
1393 color_info.h = 1;
1394 if(showcolortip)
1395 {
1396 gui_textout_ln(screen2,font,(unsigned char*)"Colors:",
1397 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1398 auto str = get_tile_colornames(tile,cs);
1399 size_t pos = 0;
1400 char buf[512] = {0};
1401 char cbuf[16] = {0};
1402 while(pos < str.size())
1403 {
1404 y += fh;
1405 if(y+fh > zq_screen_h)
1406 break; //Out of space!
1407 auto endpos = str.find_first_of('\n',pos);
1408
1409 if(endpos == std::string::npos)
1410 {
1411 strcpy(buf,str.substr(pos).c_str());
1412 pos = str.size();
1413 }
1414 else
1415 {
1416 strcpy(buf,str.substr(pos,endpos-pos+1).c_str());
1417 pos = endpos+1;
1418 }
1419 //Ensure the name fits horizontally
1420 if(text_length(font,buf) > color_info.xscale)
1421 {
1422 size_t pos = 0;
1423 for(; buf[pos]; ++pos)
1424 {
1425 if(buf[pos] == ':')
1426 {
1427 strcpy(cbuf, buf+pos);
1428 buf[pos] = 0;
1429 break;
1430 }
1431 }
1432 size_t clen = text_length(font,cbuf);
1433 size_t dotlen = text_length(font,"..");
1434
1435 while(pos > 0 && (dotlen+clen+text_length(font,buf) > color_info.xscale))
1436 buf[--pos] = 0;
1437 while(buf[pos] == ' ')
1438 buf[pos] = 0;
1439 strcat(buf,"..");
1440 strcat(buf,cbuf);
1441 }
1442 gui_textout_ln(screen2,font,(unsigned char const*)buf,
1443 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1444 ++color_info.h;
1445 }
1446 jwin_draw_frame(screen2,color_info.x-2,color_info.y-2,(color_info.w*color_info.xscale)+4,(color_info.h*color_info.yscale)+4,FR_DEEP);
1447 }
1448 else
1449 {
1450 draw_text_button(screen2,color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,
1451 "Show Colors",vc(1),vc(14),0,true);
1452 }
1453 }
1454
1455 zc_swap(tmpptr,newtilebuf[tile].data); //Swap the real tile back to the buffer
1456
1457 jwin_draw_win(screen2, zoomtile.x-3, zoomtile.y-3, (zoomtile.w*zoomtile.xscale)+5, (zoomtile.h*zoomtile.yscale)+5, FR_DEEP);
1458 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
1459
1460 if(floating_sel)
1461 textprintf_ex(screen2,font,status_info.x,status_info.y+0,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Floating selection");
1462 textprintf_ex(screen2,font,status_info.x,status_info.y+(1*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile: %d",tile);
1463 if(newtilebuf[tile].format==tf8Bit)
1464 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"8-bit");
1465 else
1466 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cset: %d",cs);
1467
1468 PALETTE temppal;
1469
1470 //palette and mouse
1471 switch(newtilebuf[tile].format)
1472 {
1473 case tf4Bit:
1474 jwin_draw_win(screen2, cpalette_4.x-2, cpalette_4.y-2, (cpalette_4.xscale*cpalette_4.w)+4, (cpalette_4.yscale*cpalette_4.h)+4, FR_DEEP);
1475 get_palette(temppal);
1476
1477 for(int32_t i=0; i<cpalette_4.w*cpalette_4.h; i++)
1478 {
1479 size_and_pos const& s = cpalette_4.subsquare(i);
1480 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,CSET(cs)+i);
1481 }
1482
1483 little_x(screen2,cpalette_4.x+1,cpalette_4.y+1,invcol,cpalette_4.xscale-5,cpalette_4.yscale-5);
1484 break;
1485
1486 case tf8Bit:
1487 jwin_draw_win(screen2, cpalette_8.x-2, cpalette_8.y-2, (cpalette_8.xscale*cpalette_8.w)+4, (cpalette_8.yscale*cpalette_8.h)+4, FR_DEEP);
1488
1489 for(int32_t i=0; i<cpalette_8.w*cpalette_8.h; ++i)
1490 {
1491 size_and_pos const& s = cpalette_8.subsquare(i);
1492 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,i);
1493 }
1494
1495 little_x(screen2,cpalette_8.x+1,cpalette_8.y+1,invcol,cpalette_8.xscale-5,cpalette_8.yscale-5);
1496 break;
1497 }
1498
1499 rect(screen2, bg_prev.x, bg_prev.y, bg_prev.x+bg_prev.w-1, bg_prev.y+bg_prev.h-1, jwin_pal[jcTEXTFG]);
1500 rectfill(screen2, bg_prev.x+1, bg_prev.y+1, bg_prev.x+bg_prev.w-2, bg_prev.y+bg_prev.h-2, jwin_pal[jcTEXTBG]);
1501 rectfill(screen2, bg_prev.x+3, bg_prev.y+3, bg_prev.x+bg_prev.w-4, bg_prev.y+bg_prev.h-4, c2+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1502
1503 if(c2==0)
1504 {
1505 little_x(screen2, bg_prev.x+1, bg_prev.y+1, invcol, bg_prev.w-2, bg_prev.h-2);
1506 }
1507
1508 rect(screen2, fg_prev.x, fg_prev.y, fg_prev.x+fg_prev.w-1, fg_prev.y+fg_prev.h-1, jwin_pal[jcTEXTFG]);
1509 rectfill(screen2, fg_prev.x+1, fg_prev.y+1, fg_prev.x+fg_prev.w-2, fg_prev.y+fg_prev.h-2, jwin_pal[jcTEXTBG]);
1510 rectfill(screen2, fg_prev.x+3, fg_prev.y+3, fg_prev.x+fg_prev.w-4, fg_prev.y+fg_prev.h-4, c1+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1511
1512 if(c1==0)
1513 {
1514 little_x(screen2, fg_prev.x+1, fg_prev.y+1, invcol, fg_prev.w-2, fg_prev.h-2);
1515 }
1516
1517 draw_text_button(screen2,ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK",vc(1),vc(14),0,true);
1518 draw_text_button(screen2,cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel",vc(1),vc(14),0,true);
1519 draw_text_button(screen2,edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal",vc(1),vc(14),0,true);
1520 draw_checkbox(screen2,hlcbox.x, hlcbox.y, hlcbox.w, hlcbox.h, tthighlight);
1521 gui_textout_ln(screen2,font,(unsigned char*)"Highlight Hover",hlcbox.x+hlcbox.w+2,hlcbox.y+hlcbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1522
1523 draw_checkbox(screen2,quartgrid_cbox.x, quartgrid_cbox.y, quartgrid_cbox.w, quartgrid_cbox.h, show_quartgrid);
1524 gui_textout_ln(screen2,font,(unsigned char*)"Quarter Grid",quartgrid_cbox.x+quartgrid_cbox.w+2,quartgrid_cbox.y+quartgrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1525
1526 draw_checkbox(screen2,hidegrid_cbox.x, hidegrid_cbox.y, hidegrid_cbox.w, hidegrid_cbox.h, hide_grid);
1527 gui_textout_ln(screen2,font,(unsigned char*)"Hide Grid",hidegrid_cbox.x+hidegrid_cbox.w+2,hidegrid_cbox.y+hidegrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1528
1529 bool qgrd = show_quartgrid && qgrid_tool(tool);
1530 gui_textout_ln(screen2,font,(unsigned char*)"Quarter-Grid Draw Modes", reflbtn_grid.x, reflbtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],qgrd?0:D_DISABLED);
1531 for(int q = 0; q < REFL_MAX; ++q)
1532 {
1533 auto& sqr = reflbtn_grid.subsquare(q);
1534 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[q],vc(1),vc(14),qgrd ? ((refl_flags&(1<<q)) ? D_SELECTED : 0) : D_DISABLED,true);
1535 }
1536 gui_textout_ln(screen2,font,(unsigned char*)"Transparent Mode", xmodebtn_grid.x, xmodebtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1537 for(int q = 0; q < XMODE_MAX; ++q)
1538 {
1539 auto& sqr = xmodebtn_grid.subsquare(q);
1540 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[q],vc(1),vc(14),(xmode == q) ? D_SELECTED : 0,true);
1541 }
1542 for(int q = 0; q < BGMODE_MAX; ++q)
1543 {
1544 auto& sqr = bgmodebtn_grid.subsquare(q);
1545 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[q],vc(1),vc(14),(bgmode == q) ? D_SELECTED : 0,true);
1546 }
1547
1548 //tool buttons
1549 for(int32_t toolbtn = 0; toolbtn < t_max; ++toolbtn)
1550 {
1551 auto bmp = toolbtn+MOUSE_BMP_SWORD;
1552 int col = toolbtn%tool_btns.w;
1553 int row = toolbtn/tool_btns.w;
1554
1555 jwin_draw_button(screen2,tool_btns.x+(col*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale,tool==toolbtn?2:0,0);
1556 masked_stretch_blit(mouse_bmp_1x[bmp][0],screen2,0,0,16,16,tool_btns.x+(col*tool_btns.xscale)+3+(tool==toolbtn?1:0),tool_btns.y+3+(row*tool_btns.yscale)+(tool==toolbtn?1:0),tool_btns.xscale-7,tool_btns.yscale-7);
1557 }
1558
1559 //coordinates
1560 {
1561 auto mx = gui_mouse_x();
1562 auto my = gui_mouse_y();
1563 int32_t ind = zoomtile.rectind(mx,my);
1564 int32_t temp_x=ind%zoomtile.w;
1565 int32_t temp_y=ind/zoomtile.w;
1566 int color = -1;
1567
1568 bool is8b = newtilebuf[tile].format > tf4Bit;
1569 if(ind > -1)
1570 {
1571 char xbuf[16];
1572 sprintf(xbuf, "x: %d", temp_x);
1573 textprintf_ex(screen2,font,status_info.x,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%s",xbuf);
1574 textprintf_ex(screen2,font,status_info.x+text_length(font,xbuf)+8,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"y: %d",temp_y);
1575 unpack_tile(newtilebuf, tile, 0, false);
1576 byte *si = unpackbuf;
1577 si+=ind;
1578 color = *si;
1579 }
1580 else if(fg_prev.rect(mx,my))
1581 color = c1;
1582 else if(bg_prev.rect(mx,my))
1583 color = c2;
1584 else color = (is8b ? cpalette_8 : cpalette_4).rectind(mx,my);
1585 if(color > -1)
1586 {
1587 get_palette(tpal);
1588 char separator = ' ';
1589 char buf[512] = {0};
1590
1591 int realcol = color+(is8b?0:CSET(cs));
1592 bool xcolor = (is8b ? realcol == 0 : (realcol%16)==0);
1593 auto& c = tpal[realcol];
1594
1595 if(tthighlight)
1596 {
1597 size_and_pos const& mainsqr = is8b ? cpalette_8 : cpalette_4;
1598 size_and_pos const& csqr = mainsqr.subsquare(color);
1599
1600 int hlcol = getHighlightColor(tpal[realcol]);
1601 int hlthick = 4;
1602 int extraborder = is8b ? 8 : 0;
1603 int borderthick = hlthick+extraborder;
1604
1605 if(is8b)
1606 {
1607 highlight_sqr(screen2, 0xED, csqr.x, mainsqr.y, csqr.w, mainsqr.h*mainsqr.yscale, hlthick); //column
1608 highlight_sqr(screen2, 0xED, mainsqr.x, csqr.y, mainsqr.w*mainsqr.xscale, csqr.h, hlthick); //row
1609 }
1610 highlight_sqr(screen2, 0xED, csqr.x-borderthick, csqr.y-borderthick, csqr.w+borderthick*2, csqr.h+borderthick*2, hlthick); //square hl
1611 rectfill(screen2, csqr.x-extraborder, csqr.y-extraborder, csqr.x+csqr.w-1+extraborder, csqr.y+csqr.h-1+extraborder, realcol); //square color
1612 if(xcolor)
1613 little_x(screen2, csqr.x-extraborder+4, csqr.y-extraborder+4, invcol, csqr.w+(extraborder*2)-8, csqr.h+(extraborder*2)-8); //transparent X
1614 highlight_sqr(screen2, hlcol, csqr.x-extraborder, csqr.y-extraborder, csqr.w+extraborder*2, csqr.h+extraborder*2, 1); //highlight border
1615 }
1616
1617 sprintf(buf, "%02d %02d %02d %c(0x%02X %d)",c.r,c.g,c.b,separator,realcol,color);
1618 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(2*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1619
1620 strcpy(buf, get_color_name(realcol, is8b).c_str());
1621 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(1*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1622
1623 sprintf(buf, "#%02X%02X%02X", tpal[realcol].r*4,tpal[realcol].g*4,tpal[realcol].b*4);
1624 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(0),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1625
1626 rect(screen2, hov_prev.x, hov_prev.y, hov_prev.x+hov_prev.w-1, hov_prev.y+hov_prev.h-1, jwin_pal[jcTEXTFG]);
1627 rectfill(screen2, hov_prev.x+1, hov_prev.y+1, hov_prev.x+hov_prev.w-2, hov_prev.y+hov_prev.h-2, jwin_pal[jcTEXTBG]);
1628 rectfill(screen2, hov_prev.x+3, hov_prev.y+3, hov_prev.x+hov_prev.w-4, hov_prev.y+hov_prev.h-4, realcol);
1629 if(xcolor)
1630 little_x(screen2, hov_prev.x+1, hov_prev.y+1, invcol, hov_prev.w-2, hov_prev.h-2);
1631 }
1632 }
1633
1634 custom_vsync();
1635 blit(screen2,screen,0,0,0,0,zq_screen_w,zq_screen_w);
1636 update_tool_cursor();
1637 SCRFIX();
1638 }
1639
1640 void normalize(int32_t tile,int32_t tile2, bool rect_sel, int32_t flip)
1641 {
1642 unfloat_selection();
1643 if(tile>tile2)
1644 {
1645 zc_swap(tile, tile2);
1646 }
1647
1648 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
1649 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
1650
1651 int32_t start=tile;
1652 int32_t end=tile2;
1653
1654 // Might have top-right and bottom-left corners selected...
1655 if(rect_sel && TILECOL(tile)>TILECOL(tile2))
1656 {
1657 start=tile-(TILECOL(tile)-TILECOL(tile2));
1658 end=tile2+(TILECOL(tile)-TILECOL(tile2));
1659 }
1660
1661 for(int32_t temptile=start; temptile<=end; temptile++)
1662 {
1663 if(!rect_sel || ((TILECOL(temptile)>=left) && (TILECOL(temptile)<=left+columns-1)))
1664 {
1665 unpack_tile(newtilebuf, temptile, 0, true);
1666
1667 if(flip&1)
1668 {
1669 for(int32_t y=0; y<16; y++)
1670 {
1671 for(int32_t x=0; x<8; x++)
1672 {
1673 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[(y<<4)+15-x]);
1674 }
1675 }
1676 }
1677
1678 if(flip&2)
1679 {
1680 for(int32_t y=0; y<8; y++)
1681 {
1682 for(int32_t x=0; x<16; x++)
1683 {
1684 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[((15-y)<<4)+x]);
1685 }
1686 }
1687 }
1688
1689 pack_tile(newtilebuf,unpackbuf,temptile);
1690 }
1691 }
1692 }
1693
1694 void rotate_tile(int32_t tile, bool backward)
1695 {
1696 unfloat_selection();
1697 unpack_tile(newtilebuf, tile, 0, true);
1698 byte tempunpackbuf[256];
1699 byte tempx, tempy;
1700
1701 for(tempx=0; tempx<16; tempx++)
1702 {
1703 for(tempy=0; tempy<16; tempy++)
1704 {
1705 if(!backward)
1706 {
1707 tempunpackbuf[(tempy<<4)+tempx]=unpackbuf[((15-tempx)<<4)+tempy];
1708 }
1709 else
1710 {
1711 tempunpackbuf[((15-tempx)<<4)+tempy]=unpackbuf[(tempy<<4)+tempx];
1712 }
1713 }
1714 }
1715
1716 pack_tile(newtilebuf,tempunpackbuf,tile);
1717 }
1718
1719 static int32_t undocount=128;
1720 byte undotile[256];
1721
1722 void wrap_tile(int32_t tile, int32_t vertical, int32_t horizontal, bool clear)
1723 {
1724 byte buf[256];
1725
1726 for(int32_t i=0; i<undocount; i++)
1727 {
1728 newtilebuf[tile].data[i]=undotile[i];
1729 }
1730
1731 if(!(horizontal||vertical))
1732 {
1733 return;
1734 }
1735
1736 unpack_tile(newtilebuf, tile, 0, true);
1737
1738 for(int32_t i=0; i<256; i++)
1739 {
1740 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1741 buf[shift_ind] = unpackbuf[i];
1742 }
1743
1744 if(clear)
1745 {
1746 for(int32_t r=0; r<abs(vertical); r++)
1747 {
1748 for(int32_t c=0; c<16; c++)
1749 {
1750 buf[(vertical>0?r:15-r)*16+c]=0;
1751 }
1752 }
1753
1754 for(int32_t r=0; r<16; r++)
1755 {
1756 for(int32_t c=0; c<abs(horizontal); c++)
1757 {
1758 buf[r*16+(horizontal>0?c:15-c)]=0;
1759 }
1760 }
1761 }
1762
1763 pack_tile(newtilebuf,buf,tile);
1764 }
1765
1766 void wrap_sel_tile(int32_t vertical, int32_t horizontal)
1767 {
1768 byte buf[256];
1769
1770 if(!(horizontal||vertical))
1771 {
1772 return;
1773 }
1774
1775 memset(buf,0,256);
1776
1777 for(int32_t i=0; i<256; i++)
1778 {
1779 if(is_in_selection(i%16,i/16))
1780 {
1781 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1782 buf[shift_ind] = floatsel[i];
1783 }
1784 }
1785
1786 memcpy(floatsel,buf,256);
1787 }
1788
1789 void float_selection(int32_t tile, bool clear)
1790 {
1791 if(floating_sel) return;
1792 floating_sel = true;
1793 floating_tile = tile;
1794
1795 unpack_tile(newtilebuf, tile, 0, true);
1796
1797 for(auto q = 0; q < 256; ++q)
1798 {
1799 if(is_in_selection(q%16,q/16))
1800 {
1801 floatsel[q] = unpackbuf[q];
1802 unpackbuf[q] = clear ? 0 : c2;
1803 }
1804 else floatsel[q] = 0;
1805 }
1806
1807 pack_tile(newtilebuf,unpackbuf,tile);
1808 }
1809
1810 void unfloat_selection()
1811 {
1812 if(!floating_sel) return;
1813 floating_sel = false;
1814
1815 unpack_tile(newtilebuf, floating_tile, 0, true);
1816
1817 for(auto q = 0; q < 256; ++q)
1818 {
1819 if(floatsel[q])
1820 {
1821 unpackbuf[q] = floatsel[q];
1822 }
1823 }
1824
1825 pack_tile(newtilebuf,unpackbuf,floating_tile);
1826 floating_tile = -1;
1827 }
1828
1829 void shift_tile_colors(int32_t tile, int32_t amount, bool ignore_transparent)
1830 {
1831 if(floating_sel)
1832 {
1833 for(auto q = 0; q < 256; ++q)
1834 {
1835 if(ignore_transparent && floatsel[q]==0)
1836 continue;
1837 floatsel[q]=wrap(floatsel[q]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1838 }
1839 return;
1840 }
1841
1842 byte buf[256];
1843 unpack_tile(newtilebuf, tile, 0, true);
1844
1845 for(int32_t i=0; i<256; i++)
1846 {
1847 buf[i]=unpackbuf[i];
1848
1849 if(!is_in_selection(i&0x0F, (i&0xF0)>>4))
1850 continue;
1851
1852 if(ignore_transparent)
1853 {
1854 if(buf[i]==0)
1855 continue;
1856
1857 buf[i]=wrap(buf[i]+amount, 1, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1858 }
1859 else // Don't ignore transparent
1860 buf[i]=wrap(buf[i]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1861 }
1862
1863 pack_tile(newtilebuf,buf,tile);
1864 }
1865
1866 void clear_selection_grid()
1867 {
1868 unfloat_selection();
1869 for(int32_t x=0; x<18; ++x)
1870 {
1871 for(int32_t y=0; y<18; ++y)
1872 {
1873 selection_grid[x][y]=0;
1874 }
1875 }
1876 }
1877
1878 void invert_selection_grid()
1879 {
1880 unfloat_selection();
1881 for(int32_t x=1; x<17; ++x)
1882 {
1883 for(int32_t y=1; y<17; ++y)
1884 {
1885 selection_grid[x][y]=selection_grid[x][y]?0:1;
1886 }
1887 }
1888 }
1889
1890 void shift_selection_grid(int32_t xoffs, int32_t yoffs)
1891 {
1892 byte local_grid[16][16];
1893 memset(local_grid, 0, sizeof(local_grid));
1894 for(auto x = 0; x < 16; ++x)
1895 {
1896 for(auto y = 0; y < 16; ++y)
1897 {
1898 auto offs_x = (x+xoffs)%16, offs_y = (y+yoffs)%16;
1899 if(offs_x < 0) offs_x = (16 - abs(offs_x));
1900 if(offs_y < 0) offs_y = (16 - abs(offs_y));
1901 local_grid[offs_x][offs_y] = selection_grid[x+1][y+1]?1:0;
1902 }
1903 }
1904 for(auto x = 0; x < 16; ++x)
1905 {
1906 for(auto y = 0; y < 16; ++y)
1907 {
1908 selection_grid[x+1][y+1] = local_grid[x][y]?1:0;
1909 }
1910 }
1911 }
1912
1913 void show_edit_tile_help()
1914 {
1915 InfoDialog("Help: Tile Editor", "Hotkeys:"
1916 "\nF1: This Help Dialog"
1917 "\nEnter: Unfloat Sel / OK | Esc: Unfloat Sel / Cancel"
1918 "\nDelete: Clear Tile/Sel | Ctrl+Delete: Clear Tile"
1919 "\nA: Sel All | D: Unselect Sel | I: Invert Sel"
1920 "\nH/V: Flip | (Shift+)R: Rotate"
1921 "\n+/-: Change CSet | Ctrl +/-: Shift Colors"
1922 "\n(Ctrl+)S: Swap Colors | U/Ctrl+Z: Undo"
1923 "\nF12: Screenshot (whole screen)"
1924 "\nArrows: Shift Pixel | Ctrl+Arrows: Change Tile"
1925 "\nWhen not on Select tools, hold to swap:"
1926 "\nCtrl - Fill | Alt - Grab | Ctrl+Alt - Recolor").show();
1927 }
1928
1929 static int move_origin_x=-1, move_origin_y=-1;
1930 static int prev_x=-1, prev_y=-1;
1931 bool __pixel_draw(int x, int y, int tile, int flip)
1932 {
1933 bool ret = false;
1934 switch(tool)
1935 {
1936 case t_pen:
1937 if(flip&1) x=15-x;
1938
1939 if(flip&2) y=15-y;
1940
1941 if(is_in_selection(x,y))
1942 {
1943 if(floating_sel)
1944 {
1945 floatsel[(y<<4)+x]=(drawing==1)?c1:c2;
1946 }
1947 else
1948 {
1949 unpack_tile(newtilebuf, tile, 0, false);
1950 unpackbuf[((y<<4)+x)]=(drawing==1)?c1:c2;
1951 pack_tile(newtilebuf, unpackbuf,tile);
1952 }
1953 }
1954 break;
1955
1956 case t_fill:
1957 if(is_in_selection(x,y))
1958 {
1959 tile_floodfill(tile,x,y,(drawing==1)?c1:c2);
1960 ret = true;
1961 }
1962 break;
1963
1964 case t_recolor:
1965 if(is_in_selection(x,y))
1966 {
1967 if(floating_sel)
1968 {
1969 tf_u = floatsel[(y<<4)+x];
1970 for(int32_t i=0; i<256; i++)
1971 {
1972 if(is_in_selection(i&15,i>>4))
1973 {
1974 if(floatsel[i]==tf_u)
1975 {
1976 floatsel[i]=(drawing==1)?c1:c2;
1977 }
1978 }
1979 }
1980 }
1981 else
1982 {
1983 unpack_tile(newtilebuf, tile, 0, false);
1984 tf_u = unpackbuf[(y<<4)+x];
1985 if(tf_u != ((drawing==1)?c1:c2))
1986 {
1987 for(int32_t i=0; i<256; i++)
1988 {
1989 if(is_in_selection(i&15,i>>4))
1990 {
1991 if(unpackbuf[i]==tf_u)
1992 {
1993 unpackbuf[i]=(drawing==1)?c1:c2;
1994 }
1995 }
1996 }
1997
1998 pack_tile(newtilebuf, unpackbuf,tile);
1999 }
2000 }
2001 ret = true;
2002 }
2003 break;
2004
2005 case t_eyedropper:
2006 if(floating_sel)
2007 memcpy(unpackbuf, floatsel, 256);
2008 else unpack_tile(newtilebuf, tile, 0, false);
2009
2010 if(gui_mouse_b()&1)
2011 {
2012 c1=unpackbuf[((y<<4)+x)];
2013 }
2014
2015 if(gui_mouse_b()&2)
2016 {
2017 c2=unpackbuf[((y<<4)+x)];
2018 }
2019 break;
2020
2021 case t_move:
2022 if((prev_x!=x)||(prev_y!=y))
2023 {
2024 if(has_selection())
2025 {
2026 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2027 wrap_sel_tile(y-prev_y, x-prev_x);
2028 shift_selection_grid(x-prev_x, y-prev_y);
2029 }
2030 else wrap_tile(tile, y-move_origin_y, x-move_origin_x, drawing==2);
2031 prev_x=x;
2032 prev_y=y;
2033 }
2034 break;
2035
2036 case t_select:
2037 unfloat_selection();
2038 if(flip&1) x=15-x;
2039
2040 if(flip&2) y=15-y;
2041
2042 if(selecting_x1==-1||selecting_y1==-1)
2043 {
2044 selecting_x1=x;
2045 selecting_y1=y;
2046 }
2047 else
2048 {
2049 selecting_x2=x;
2050 selecting_y2=y;
2051 }
2052 break;
2053
2054 case t_wand:
2055 unfloat_selection();
2056 if(flip&1) x=15-x;
2057
2058 if(flip&2) y=15-y;
2059
2060 switch(select_mode)
2061 {
2062 case 0:
2063 clear_selection_grid();
2064 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2065 break;
2066
2067 case 1:
2068 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2069 break;
2070
2071 case 2:
2072 remove_color_from_selection(unpackbuf[((y<<4)+x)]);
2073 break;
2074
2075 case 3:
2076 intersect_color_with_selection(unpackbuf[((y<<4)+x)]);
2077 break;
2078 }
2079
2080 ret = true;
2081 break;
2082 }
2083 return ret;
2084 }
2085 void edit_tile(int32_t tile,int32_t flip,int32_t &cs)
2086 {
2087 popup_zqdialog_start();
2088 FONT* oldfont = font;
2089 font = get_custom_font(CFONT_DLG);
2090 edit_button.h = ok_button.h = cancel_button.h = 12+text_height(font);
2091 status_info.yscale = text_height(font);
2092 status_info.y = 308-(status_info.h*status_info.yscale);
2093 hover_info.yscale = status_info.yscale;
2094 hover_info.y = 338-(hover_info.h*hover_info.yscale);
2095 go();
2096 undocount = tilesize(newtilebuf[tile].format);
2097 clear_selection_grid();
2098 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2099
2100 tthighlight = zc_get_config("ZQ_GUI","tile_edit_fancyhighlight",1);
2101 showcolortip = zc_get_config("ZQ_GUI","tile_edit_colornames",1);
2102
2103 PALETTE tpal;
2104 byte oldtile[256];
2105
2106 memset(&tpal, 0, sizeof(PALETTE));
2107 memset(oldtile, 0, 256);
2108
2109 for(int32_t i=0; i<undocount; i++)
2110 {
2111 oldtile[i]=undotile[i]=newtilebuf[tile].data[i];
2112 }
2113 byte undoselgrid[16][16];
2114 for(auto x = 0; x < 16; ++x)
2115 for(auto y = 0; y < 16; ++y)
2116 undoselgrid[x][y] = selection_grid[x+1][y+1];
2117 for(auto q = 0; q < 256; ++q)
2118 {
2119 floatsel[q] = 0;
2120 undofloatsel[q] = 0;
2121 floating_sel = false;
2122 undo_is_floatsel = false;
2123 }
2124
2125 int32_t tile_x=-1, tile_y=-1;
2126 int32_t temp_x=-1, temp_y=-1;
2127 bool bdown=false;
2128 int32_t done=0;
2129 drawing=0;
2130 tool_cur = -1;
2131
2132 get_palette(tpal);
2133
2134 if(newtilebuf[tile].format==tf4Bit)
2135 {
2136 invcol=makecol8((63-tpal[CSET(cs)].r)*255/63,(63-tpal[CSET(cs)].g)*255/63,(63-tpal[CSET(cs)].b)*255/63);
2137 }
2138 else
2139 {
2140 invcol=makecol8((63-tpal[0].r)*255/63,(63-tpal[0].g)*255/63,(63-tpal[0].b)*255/63);
2141 }
2142
2143 custom_vsync();
2144 zc_set_palette(tpal);
2145 draw_edit_scr(tile,flip,cs,oldtile, true);
2146
2147 while(gui_mouse_b())
2148 {
2149 /* do nothing */
2150 rest(1);
2151 }
2152
2153 move_origin_x=-1;
2154 move_origin_y=-1;
2155 prev_x=-1;
2156 prev_y=-1;
2157
2158
2159
2160 byte selection_pattern_source[8][8]=
2161 {
2162 {1, 1, 1, 1, 0, 0, 0, 0},
2163 {1, 1, 1, 0, 0, 0, 0, 1},
2164 {1, 1, 0, 0, 0, 0, 1, 1},
2165 {1, 0, 0, 0, 0, 1, 1, 1},
2166 {0, 0, 0, 0, 1, 1, 1, 1},
2167 {0, 0, 0, 1, 1, 1, 1, 0},
2168 {0, 0, 1, 1, 1, 1, 0, 0},
2169 {0, 1, 1, 1, 1, 0, 0, 0},
2170 };
2171
2172 byte selecting_pattern_source[8][8]=
2173 {
2174 {1, 1, 0, 0, 0, 0, 1, 1},
2175 {1, 0, 0, 0, 0, 1, 1, 1},
2176 {0, 0, 0, 0, 1, 1, 1, 1},
2177 {0, 0, 0, 1, 1, 1, 1, 0},
2178 {0, 0, 1, 1, 1, 1, 0, 0},
2179 {0, 1, 1, 1, 1, 0, 0, 0},
2180 {1, 1, 1, 1, 0, 0, 0, 0},
2181 {1, 1, 1, 0, 0, 0, 0, 1},
2182 };
2183
2184 byte intersection_pattern_source[8][8]=
2185 {
2186 {0, 0, 1, 1, 0, 0, 1, 1},
2187 {0, 1, 1, 0, 0, 1, 1, 0},
2188 {1, 1, 0, 0, 1, 1, 0, 0},
2189 {1, 0, 0, 1, 1, 0, 0, 1},
2190 {0, 0, 1, 1, 0, 0, 1, 1},
2191 {0, 1, 1, 0, 0, 1, 1, 0},
2192 {1, 1, 0, 0, 1, 1, 0, 0},
2193 {1, 0, 0, 1, 1, 0, 0, 1},
2194 };
2195
2196 selection_pattern=create_bitmap_ex(8, 8, 8);
2197
2198 for(int32_t x=0; x<8; ++x)
2199 {
2200 for(int32_t y=0; y<8; ++y)
2201 {
2202 selection_pattern->line[y][x]=selection_pattern_source[x][y]?vc(0):vc(15);
2203 }
2204 }
2205
2206 selecting_pattern=create_bitmap_ex(8, 8, 8);
2207
2208 for(int32_t x=0; x<8; ++x)
2209 {
2210 for(int32_t y=0; y<8; ++y)
2211 {
2212 selecting_pattern->line[y][x]=selecting_pattern_source[x][y]?vc(0):vc(15);
2213 }
2214 }
2215
2216 intersection_pattern=create_bitmap_ex(8, 8, 8);
2217
2218 for(int32_t x=0; x<8; ++x)
2219 {
2220 for(int32_t y=0; y<8; ++y)
2221 {
2222 intersection_pattern->line[y][x]=intersection_pattern_source[x][y]?vc(0):vc(15);
2223 }
2224 }
2225
2226 do
2227 {
2228 HANDLE_CLOSE_ZQDLG();
2229 if(exiting_program) break;
2230 int32_t temp_mouse_x=gui_mouse_x();
2231 int32_t temp_mouse_y=gui_mouse_y();
2232 rest(4);
2233 bool redraw=false;
2234 bool did_wand_select=false;
2235
2236 if(keypressed())
2237 {
2238 bool ctrl = CHECK_CTRL_CMD;
2239 int k = readkey()>>8;
2240 switch(k)
2241 {
2242 case KEY_F1:
2243 show_edit_tile_help();
2244 break;
2245 case KEY_ENTER_PAD:
2246 case KEY_ENTER:
2247 if(floating_sel)
2248 unfloat_selection();
2249 else done=2;
2250 break;
2251
2252 case KEY_ESC:
2253 if(floating_sel)
2254 unfloat_selection();
2255 else if(has_selection())
2256 clear_selection_grid();
2257 else done=1;
2258 break;
2259
2260 case KEY_DEL:
2261 {
2262 unpack_tile(newtilebuf, tile, 0, false);
2263 bool all = CHECK_CTRL_CMD || !has_selection();
2264 bool canDel = false;
2265 if(all)
2266 {
2267 //Check all
2268 for(auto q = 0; q < 256; ++q)
2269 if(unpackbuf[q])
2270 {
2271 canDel = true;
2272 break;
2273 }
2274 }
2275 else
2276 {
2277 //Check selection
2278 for(auto x = 0; x < 16; ++x)
2279 for(auto y = 0; y < 16; ++y)
2280 if(is_in_selection(x,y))
2281 if(unpackbuf[(y<<4)+x])
2282 {
2283 canDel = true;
2284 break;
2285 }
2286 }
2287 if(!canDel) break; //don't delete (and thus reset undo) if nothing would change!
2288
2289 for(int32_t i=0; i<undocount; i++)
2290 {
2291 undotile[i]=newtilebuf[tile].data[i];
2292 }
2293 for(auto x = 0; x < 16; ++x)
2294 for(auto y = 0; y < 16; ++y)
2295 undoselgrid[x][y] = selection_grid[x+1][y+1];
2296 for(auto q = 0; q < 256; ++q)
2297 undofloatsel[q] = floatsel[q];
2298 undo_is_floatsel = floating_sel;
2299
2300 if(CHECK_CTRL_CMD || !has_selection())
2301 {
2302 //Delete all
2303 for(auto q = 0; q < 256; ++q)
2304 {
2305 unpackbuf[q] = 0;
2306 floatsel[q] = 0;
2307 }
2308 }
2309 else
2310 {
2311 //Delete selection
2312 for(auto x = 0; x < 16; ++x)
2313 for(auto y = 0; y < 16; ++y)
2314 {
2315 if(floating_sel)
2316 {
2317 floatsel[x+(y<<4)] = 0;
2318 }
2319 else if(is_in_selection(x,y))
2320 {
2321 unpackbuf[(y<<4)+x] = 0;
2322 }
2323 }
2324 }
2325 pack_tile(newtilebuf, unpackbuf, tile);
2326 redraw=true;
2327 }
2328 break;
2329
2330 case KEY_A:
2331 clear_selection_grid();
2332 invert_selection_grid();
2333 redraw=true;
2334 break;
2335
2336 case KEY_D:
2337 clear_selection_grid();
2338 redraw=true;
2339 break;
2340
2341 case KEY_I:
2342 invert_selection_grid();
2343 redraw=true;
2344 break;
2345
2346 case KEY_H:
2347 flip^=1;
2348 normalize(tile,tile,0,flip);
2349 flip=0;
2350 redraw=true;
2351 break;
2352
2353 case KEY_V:
2354 flip^=2;
2355 normalize(tile,tile,0,flip);
2356 flip=0;
2357 redraw=true;
2358 break;
2359
2360 case KEY_F12:
2361 onSnapshot();
2362 break;
2363
2364 case KEY_R:
2365 {
2366 //if(CHECK_CTRL_CMD))
2367 // {
2368 //do_recolor(tile); redraw=true; saved=false;
2369 // }
2370 //else
2371 // {
2372 go_tiles();
2373 rotate_tile(tile,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
2374 redraw=true;
2375 saved=false;
2376 break;
2377 }
2378
2379 case KEY_EQUALS:
2380 case KEY_PLUS_PAD:
2381 {
2382 if(CHECK_CTRL_CMD ||
2383 key[KEY_ALT] || key[KEY_ALTGR])
2384 {
2385 for(int32_t i=0; i<undocount; i++)
2386 undotile[i]=newtilebuf[tile].data[i];
2387 for(auto x = 0; x < 16; ++x)
2388 for(auto y = 0; y < 16; ++y)
2389 undoselgrid[x][y] = selection_grid[x+1][y+1];
2390 for(auto q = 0; q < 256; ++q)
2391 undofloatsel[q] = floatsel[q];
2392 undo_is_floatsel = floating_sel;
2393
2394 if(key[KEY_ALT] || key[KEY_ALTGR])
2395 shift_tile_colors(tile, 16, false);
2396 else
2397 shift_tile_colors(tile, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2398 }
2399 else
2400 cs = (cs<13) ? cs+1:0;
2401
2402 redraw=true;
2403 break;
2404 }
2405
2406 case KEY_MINUS:
2407 case KEY_MINUS_PAD:
2408 {
2409 if(CHECK_CTRL_CMD ||
2410 key[KEY_ALT] || key[KEY_ALTGR])
2411 {
2412 for(int32_t i=0; i<undocount; i++)
2413 undotile[i]=newtilebuf[tile].data[i];
2414 for(auto x = 0; x < 16; ++x)
2415 for(auto y = 0; y < 16; ++y)
2416 undoselgrid[x][y] = selection_grid[x+1][y+1];
2417 for(auto q = 0; q < 256; ++q)
2418 undofloatsel[q] = floatsel[q];
2419 undo_is_floatsel = floating_sel;
2420
2421 if(key[KEY_ALT] || key[KEY_ALTGR])
2422 shift_tile_colors(tile, -16, false);
2423 else
2424 shift_tile_colors(tile, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2425 }
2426 else
2427 cs = (cs>0) ? cs-1:13;
2428
2429 redraw=true;
2430 break;
2431 }
2432
2433 case KEY_SPACE:
2434 gridmode=(gridmode+1)%gm_max;
2435 redraw=true;
2436 break;
2437
2438 case KEY_Z:
2439 if(!ctrl)
2440 break;
2441 //Ctrl+Z == undo
2442 [[fallthrough]];
2443 case KEY_U:
2444 for(int32_t i=0; i<undocount; i++)
2445 zc_swap(undotile[i],newtilebuf[tile].data[i]);
2446
2447 for(auto x = 0; x < 16; ++x)
2448 for(auto y = 0; y < 16; ++y)
2449 zc_swap(selection_grid[x+1][y+1], undoselgrid[x][y]);
2450
2451 for(auto q = 0; q < 256; ++q)
2452 zc_swap(undofloatsel[q], floatsel[q]);
2453 zc_swap(undo_is_floatsel, floating_sel);
2454
2455 redraw=true;
2456 break;
2457
2458 case KEY_S:
2459 if(CHECK_CTRL_CMD)
2460 {
2461 for(int32_t i=0; i<undocount; i++)
2462 {
2463 undotile[i]=newtilebuf[tile].data[i];
2464 }
2465 for(auto x = 0; x < 16; ++x)
2466 for(auto y = 0; y < 16; ++y)
2467 undoselgrid[x][y] = selection_grid[x+1][y+1];
2468 for(auto q = 0; q < 256; ++q)
2469 undofloatsel[q] = floatsel[q];
2470 undo_is_floatsel = floating_sel;
2471
2472 unpack_tile(newtilebuf, tile, 0, false);
2473
2474 if(has_selection())
2475 {
2476 for(int32_t i=0; i<256; i++)
2477 {
2478 if(!is_in_selection(i%16,i/16))
2479 continue;
2480 if(unpackbuf[i]==c1)
2481 {
2482 unpackbuf[i]=c2;
2483 }
2484 else if(unpackbuf[i]==c2)
2485 {
2486 unpackbuf[i]=c1;
2487 }
2488 if(floating_sel)
2489 {
2490 if(floatsel[i]==c1)
2491 {
2492 floatsel[i]=c2;
2493 }
2494 else if(floatsel[i]==c2)
2495 {
2496 floatsel[i]=c1;
2497 }
2498 }
2499 }
2500 }
2501 else
2502 {
2503 for(int32_t i=0; i<256; i++)
2504 {
2505 if(unpackbuf[i]==c1)
2506 {
2507 unpackbuf[i]=c2;
2508 }
2509 else if(unpackbuf[i]==c2)
2510 {
2511 unpackbuf[i]=c1;
2512 }
2513 }
2514 }
2515
2516 pack_tile(newtilebuf, unpackbuf,tile);
2517 }
2518
2519 zc_swap(c1,c2);
2520 redraw=true;
2521 break;
2522
2523 case KEY_UP:
2524 if(CHECK_CTRL_CMD)
2525 {
2526 unfloat_selection();
2527 tile=zc_max(0,tile-TILES_PER_ROW);
2528 undocount = tilesize(newtilebuf[tile].format);
2529
2530 for(int32_t i=0; i<undocount; i++)
2531 {
2532 undotile[i]=newtilebuf[tile].data[i];
2533 oldtile[i]=undotile[i];
2534 }
2535
2536 redraw=true;
2537 }
2538 else
2539 {
2540 for(int32_t i=0; i<undocount; i++)
2541 {
2542 undotile[i]=newtilebuf[tile].data[i];
2543 }
2544 for(auto x = 0; x < 16; ++x)
2545 for(auto y = 0; y < 16; ++y)
2546 undoselgrid[x][y] = selection_grid[x+1][y+1];
2547 for(auto q = 0; q < 256; ++q)
2548 undofloatsel[q] = floatsel[q];
2549 undo_is_floatsel = floating_sel;
2550 if(has_selection())
2551 {
2552 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2553 wrap_sel_tile(-1, 0);
2554 shift_selection_grid(0, -1);
2555 }
2556 else wrap_tile(tile, -1, 0, false);
2557 redraw=true;
2558 }
2559 break;
2560
2561 case KEY_DOWN:
2562 if(CHECK_CTRL_CMD)
2563 {
2564 unfloat_selection();
2565 tile=zc_min(tile+TILES_PER_ROW,NEWMAXTILES-1);
2566 undocount = tilesize(newtilebuf[tile].format);
2567
2568 for(int32_t i=0; i<undocount; i++)
2569 {
2570 undotile[i]=newtilebuf[tile].data[i];
2571 oldtile[i]=undotile[i];
2572 }
2573
2574 redraw=true;
2575 }
2576 else
2577 {
2578 for(int32_t i=0; i<undocount; i++)
2579 {
2580 undotile[i]=newtilebuf[tile].data[i];
2581 }
2582 for(auto x = 0; x < 16; ++x)
2583 for(auto y = 0; y < 16; ++y)
2584 undoselgrid[x][y] = selection_grid[x+1][y+1];
2585 for(auto q = 0; q < 256; ++q)
2586 undofloatsel[q] = floatsel[q];
2587 undo_is_floatsel = floating_sel;
2588 if(has_selection())
2589 {
2590 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2591 wrap_sel_tile(1, 0);
2592 shift_selection_grid(0, 1);
2593 }
2594 else wrap_tile(tile, 1, 0, false);
2595 redraw=true;
2596 }
2597 break;
2598
2599 case KEY_LEFT:
2600 if(CHECK_CTRL_CMD)
2601 {
2602 unfloat_selection();
2603 tile=zc_max(0,tile-1);
2604 undocount = tilesize(newtilebuf[tile].format);
2605
2606 for(int32_t i=0; i<undocount; i++)
2607 {
2608 undotile[i]=newtilebuf[tile].data[i];
2609 oldtile[i]=undotile[i];
2610 }
2611
2612 redraw=true;
2613 }
2614 else
2615 {
2616 for(int32_t i=0; i<undocount; i++)
2617 {
2618 undotile[i]=newtilebuf[tile].data[i];
2619 }
2620 for(auto x = 0; x < 16; ++x)
2621 for(auto y = 0; y < 16; ++y)
2622 undoselgrid[x][y] = selection_grid[x+1][y+1];
2623 for(auto q = 0; q < 256; ++q)
2624 undofloatsel[q] = floatsel[q];
2625 undo_is_floatsel = floating_sel;
2626 if(has_selection())
2627 {
2628 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2629 wrap_sel_tile(0, -1);
2630 shift_selection_grid(-1, 0);
2631 }
2632 else wrap_tile(tile, 0, -1, false);
2633 redraw=true;
2634 }
2635 break;
2636
2637 case KEY_RIGHT:
2638 if(CHECK_CTRL_CMD)
2639 {
2640 unfloat_selection();
2641 tile=zc_min(tile+1, NEWMAXTILES-1);
2642 undocount = tilesize(newtilebuf[tile].format);
2643
2644 for(int32_t i=0; i<undocount; i++)
2645 {
2646 undotile[i]=newtilebuf[tile].data[i];
2647 oldtile[i]=undotile[i];
2648 }
2649
2650 redraw=true;
2651 }
2652 else
2653 {
2654 for(int32_t i=0; i<undocount; i++)
2655 {
2656 undotile[i]=newtilebuf[tile].data[i];
2657 }
2658 for(auto x = 0; x < 16; ++x)
2659 for(auto y = 0; y < 16; ++y)
2660 undoselgrid[x][y] = selection_grid[x+1][y+1];
2661 for(auto q = 0; q < 256; ++q)
2662 undofloatsel[q] = floatsel[q];
2663 undo_is_floatsel = floating_sel;
2664 if(has_selection())
2665 {
2666 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2667 wrap_sel_tile(0, 1);
2668 shift_selection_grid(1, 0);
2669 }
2670 else wrap_tile(tile, 0, 1, false);
2671 redraw=true;
2672 }
2673 break;
2674 case KEY_0: case KEY_1: case KEY_2: case KEY_3:
2675 case KEY_4: case KEY_5: case KEY_6: case KEY_7:
2676 case KEY_8: case KEY_9:
2677 case KEY_0_PAD: case KEY_1_PAD: case KEY_2_PAD: case KEY_3_PAD:
2678 case KEY_4_PAD: case KEY_5_PAD: case KEY_6_PAD: case KEY_7_PAD:
2679 case KEY_8_PAD: case KEY_9_PAD:
2680 {
2681 int t = k - ((k>KEY_9) ? KEY_1_PAD : KEY_1);
2682 if(unsigned(t) < t_max)
2683 {
2684 if(old_tool != -1)
2685 old_tool = t;
2686 else tool = t;
2687 }
2688 break;
2689 }
2690 case KEY_TAB:
2691 {
2692 if(key_shifts & KB_CTRL_FLAG)
2693 {
2694 xmode = (xmode+1)%XMODE_MAX;
2695 if(!xmode)
2696 bgmode = (bgmode+1)%BGMODE_MAX;
2697 }
2698 else if(key_shifts & KB_SHIFT_FLAG)
2699 hide_grid = !hide_grid;
2700 else show_quartgrid = !show_quartgrid;
2701 redraw = true;
2702 break;
2703 }
2704 }
2705 clear_keybuf();
2706 }
2707
2708 if(!gui_mouse_b())
2709 {
2710 if(is_selecting())
2711 {
2712 unfloat_selection();
2713 int32_t x1=zc_min(selecting_x1,selecting_x2);
2714 int32_t x2=zc_max(selecting_x1,selecting_x2);
2715 int32_t y1=zc_min(selecting_y1,selecting_y2);
2716 int32_t y2=zc_max(selecting_y1,selecting_y2);
2717
2718 if(select_mode==0)
2719 {
2720 clear_selection_grid();
2721 }
2722
2723 for(int32_t x=x1; x<=x2; ++x)
2724 {
2725 for(int32_t y=y1; y<=y2; ++y)
2726 {
2727 selection_grid[x+1][y+1]=((select_mode<2)?(1):(((select_mode==2)?(0):(selection_grid[x+1][y+1]))));
2728 }
2729 }
2730
2731 if(select_mode==3)
2732 {
2733 for(int32_t y=0; y<16; ++y)
2734 {
2735 for(int32_t x=0; x<x1; ++x)
2736 {
2737 selection_grid[x+1][y+1]=0;
2738 }
2739
2740 for(int32_t x=x2+1; x<16; ++x)
2741 {
2742 selection_grid[x+1][y+1]=0;
2743 }
2744 }
2745
2746 for(int32_t x=x1; x<=x2; ++x)
2747 {
2748 for(int32_t y=0; y<y1; ++y)
2749 {
2750 selection_grid[x+1][y+1]=0;
2751 }
2752
2753 for(int32_t y=y2+1; y<16; ++y)
2754 {
2755 selection_grid[x+1][y+1]=0;
2756 }
2757 }
2758 }
2759 }
2760
2761 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2762 did_wand_select=false;
2763 }
2764
2765 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
2766 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2767 bool ctrl=CHECK_CTRL_CMD;
2768 static int32_t last_tool_val = 0;
2769
2770 if(tool==t_select||tool==t_wand)
2771 {
2772 if(!drawing)
2773 {
2774 int32_t type=0;
2775
2776 if(has_selection())
2777 {
2778 if(shift)
2779 {
2780 type+=1;
2781 }
2782
2783 if(alt)
2784 {
2785 type+=2;
2786 }
2787 }
2788
2789 if(type!=select_mode)
2790 {
2791 select_mode=type;
2792
2793 if(isinRect(temp_mouse_x,temp_mouse_y-(tool==t_fill ? (14) : 0),zoomtile.x,zoomtile.y,zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2794 set_tool_sprite(tool,type);
2795 }
2796 }
2797 }
2798 else if(alt||ctrl)
2799 {
2800 if(old_tool==-1)
2801 {
2802 old_tool = tool;
2803 tool_cur = -1;
2804 }
2805 if(alt&&ctrl)
2806 tool = t_recolor;
2807 else if(alt)
2808 tool = t_eyedropper;
2809 else tool = t_fill;
2810 }
2811 else if(old_tool!=-1)
2812 {
2813 tool = old_tool;
2814 old_tool = -1;
2815 tool_cur = -1;
2816 redraw = true;
2817 }
2818 if(last_tool_val != tool)
2819 {
2820 redraw = true;
2821 tool_cur = -1;
2822 update_tool_cursor();
2823 last_tool_val = tool;
2824 }
2825
2826 if(!bdown)
2827 {
2828 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2829 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2830 }
2831
2832 if(gui_mouse_b()==1 && !bdown) //pressed the left mouse button
2833 {
2834 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2835 {
2836 if(tool==t_move || tool==t_fill)
2837 {
2838 set_tool_sprite(tool,1);
2839
2840 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2841 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2842 }
2843
2844 for(int32_t i=0; i<undocount; i++)
2845 {
2846 undotile[i]=newtilebuf[tile].data[i];
2847 }
2848 for(auto x = 0; x < 16; ++x)
2849 for(auto y = 0; y < 16; ++y)
2850 undoselgrid[x][y] = selection_grid[x+1][y+1];
2851 for(auto q = 0; q < 256; ++q)
2852 undofloatsel[q] = floatsel[q];
2853 undo_is_floatsel = floating_sel;
2854
2855 drawing=1;
2856 }
2857
2858 if(ok_button.rect(temp_mouse_x,temp_mouse_y))
2859 {
2860 if(do_text_button(ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK"))
2861 {
2862 done=2;
2863 }
2864 }
2865
2866 if(cancel_button.rect(temp_mouse_x,temp_mouse_y))
2867 {
2868 if(do_text_button(cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel"))
2869 {
2870 done=1;
2871 }
2872 }
2873
2874 if(edit_button.rect(temp_mouse_x,temp_mouse_y))
2875 {
2876 if(do_text_button(edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal"))
2877 {
2878 colors_menu.pop(edit_button.x+2,edit_button.y-40);
2879 get_palette(tpal);
2880
2881 if(newtilebuf[tile].format==tf4Bit)
2882 {
2883 invcol=makecol8((63-tpal[CSET(cs)].r)*255/63,(63-tpal[CSET(cs)].g)*255/63,(63-tpal[CSET(cs)].b)*255/63);
2884 }
2885 else
2886 {
2887 invcol=makecol8((63-tpal[0].r)*255/63,(63-tpal[0].g)*255/63,(63-tpal[0].b)*255/63);
2888 }
2889
2890 redraw=true;
2891 }
2892 }
2893
2894 int sqr_clicked;
2895 if(show_quartgrid && qgrid_tool(tool))
2896 {
2897 sqr_clicked = reflbtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2898 if(sqr_clicked > -1)
2899 {
2900 auto& sqr = reflbtn_grid.subsquare(sqr_clicked);
2901 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[sqr_clicked]))
2902 refl_flags ^= (1<<sqr_clicked);
2903 }
2904 }
2905 sqr_clicked = xmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2906 if(sqr_clicked > -1)
2907 {
2908 auto& sqr = xmodebtn_grid.subsquare(sqr_clicked);
2909 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[sqr_clicked]))
2910 xmode = sqr_clicked;
2911 }
2912 sqr_clicked = bgmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2913 if(sqr_clicked > -1)
2914 {
2915 auto& sqr = bgmodebtn_grid.subsquare(sqr_clicked);
2916 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[sqr_clicked]))
2917 bgmode = sqr_clicked;
2918 }
2919
2920 if(showcolortip)
2921 {
2922 if(color_info.rect(temp_mouse_x,temp_mouse_y))
2923 {
2924 showcolortip = 0;
2925 zc_set_config("ZQ_GUI","tile_edit_colornames",0);
2926 }
2927 }
2928 else
2929 {
2930 if(color_info_btn.rect(temp_mouse_x,temp_mouse_y))
2931 {
2932 if(do_text_button(color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,"Show Colors"))
2933 {
2934 showcolortip = 1;
2935 zc_set_config("ZQ_GUI","tile_edit_colornames",1);
2936 redraw=true;
2937 }
2938 }
2939 }
2940
2941 if(hlcbox.rect(temp_mouse_x,temp_mouse_y))
2942 {
2943 if(do_checkbox(screen2,hlcbox.x,hlcbox.y,hlcbox.w,hlcbox.h,tthighlight))
2944 {
2945 zc_set_config("ZQ_GUI","tile_edit_fancyhighlight",tthighlight);
2946 redraw=true;
2947 }
2948 }
2949 if(quartgrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2950 {
2951 if(do_checkbox(screen2,quartgrid_cbox.x,quartgrid_cbox.y,quartgrid_cbox.w,quartgrid_cbox.h,show_quartgrid))
2952 redraw=true;
2953 }
2954 if(hidegrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2955 {
2956 if(do_checkbox(screen2,hidegrid_cbox.x,hidegrid_cbox.y,hidegrid_cbox.w,hidegrid_cbox.h,hide_grid))
2957 redraw=true;
2958 }
2959
2960 switch(newtilebuf[tile].format)
2961 {
2962 case tf4Bit:
2963 {
2964 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
2965 if(ind > -1)
2966 {
2967 c1 = ind;
2968 redraw=true;
2969 }
2970 break;
2971 }
2972 case tf8Bit:
2973 {
2974 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
2975 if(ind > -1)
2976 {
2977 c1 = ind;
2978 redraw=true;
2979 }
2980 break;
2981 }
2982 }
2983
2984
2985 int32_t newtool = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
2986 if(newtool > -1 && newtool < t_max)
2987 {
2988 tool=newtool;
2989 redraw=true;
2990 }
2991
2992 if(x_btn.rect(temp_mouse_x,temp_mouse_y))
2993 {
2994 if(do_x_button(screen, x_btn.x, x_btn.y))
2995 {
2996 done=1;
2997 }
2998 }
2999 if(info_btn.rect(temp_mouse_x,temp_mouse_y))
3000 {
3001 if(do_question_button(screen, info_btn.x, info_btn.y))
3002 {
3003 show_edit_tile_help();
3004 }
3005 }
3006
3007 bdown=true;
3008 }
3009
3010 if(gui_mouse_b()&2 && !bdown) //pressed the right mouse button
3011 {
3012 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3013 {
3014 if(tool==t_move || tool==t_fill)
3015 {
3016 set_tool_sprite(tool,1);
3017
3018 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
3019 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
3020 }
3021
3022 for(int32_t i=0; i<undocount; i++)
3023 {
3024 undotile[i]=newtilebuf[tile].data[i];
3025 }
3026 for(auto x = 0; x < 16; ++x)
3027 for(auto y = 0; y < 16; ++y)
3028 undoselgrid[x][y] = selection_grid[x+1][y+1];
3029 for(auto q = 0; q < 256; ++q)
3030 undofloatsel[q] = floatsel[q];
3031 undo_is_floatsel = floating_sel;
3032
3033 drawing=2;
3034 }
3035
3036 switch(newtilebuf[tile].format)
3037 {
3038 case tf4Bit:
3039 {
3040 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
3041 if(ind > -1)
3042 {
3043 c2 = ind;
3044 redraw=true;
3045 }
3046 break;
3047 }
3048 case tf8Bit:
3049 {
3050 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
3051 if(ind > -1)
3052 {
3053 c2 = ind;
3054 redraw=true;
3055 }
3056 break;
3057 }
3058 }
3059
3060 bdown=true;
3061 }
3062
3063 if(bdown&&!gui_mouse_b()) //released the buttons
3064 {
3065 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3066 {
3067 if(tool==t_move || tool==t_fill)
3068 {
3069 set_tool_sprite(tool,0);
3070 }
3071 }
3072 }
3073
3074 if(drawing && zoomtile.rect(temp_mouse_x,temp_mouse_y)) //inside the zoomed tile window
3075 {
3076 int32_t ind = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3077 int32_t x=ind%zoomtile.w;
3078 int32_t y=ind/zoomtile.w;
3079
3080 bool reset_draw = false;
3081
3082 if(__pixel_draw(x,y,tile,flip))
3083 reset_draw = true;
3084 if(show_quartgrid)
3085 {
3086 auto tmp_sel_mode = select_mode;
3087 if(tool == t_wand && select_mode == 0)
3088 select_mode = 1;
3089 if(qgrid_tool(tool))
3090 {
3091 if(refl_flags & (1<<REFL_HFLIP))
3092 if(__pixel_draw(15-x,y,tile,flip))
3093 reset_draw = true;
3094 if(refl_flags & (1<<REFL_VFLIP))
3095 if(__pixel_draw(x,15-y,tile,flip))
3096 reset_draw = true;
3097 //Diagonal flip and 180° rotation are the same!
3098 if(refl_flags & ((1<<REFL_DBLFLIP)|(1<<REFL_180)))
3099 if(__pixel_draw(15-x,15-y,tile,flip))
3100 reset_draw = true;
3101 if(refl_flags & (1<<REFL_90CW))
3102 if(__pixel_draw(15-y,x,tile,flip))
3103 reset_draw = true;
3104 if(refl_flags & (1<<REFL_90CCW))
3105 if(__pixel_draw(y,15-x,tile,flip))
3106 reset_draw = true;
3107 }
3108 select_mode = tmp_sel_mode;
3109 }
3110
3111 if(reset_draw)
3112 drawing = 0;
3113 redraw=true;
3114 }
3115
3116 if(gui_mouse_b()==0)
3117 {
3118 bdown=false;
3119 drawing=0;
3120 }
3121
3122 temp_x=(gui_mouse_x()-zoomtile.x)/zoomtile.xscale;
3123 temp_y=(gui_mouse_y()-zoomtile.y)/zoomtile.yscale;
3124
3125 {
3126 tile_x=temp_x;
3127 tile_y=temp_y;
3128 redraw=true;
3129 }
3130
3131 const char *toolnames[t_max]=
3132 {
3133 "Pen\nDraw Single Pixels", "Fill\nCtrl", "Replace Color\nCtrl+Alt", "Grab Color\nAlt", "Move\nMove Selections", "Select Pixels", "Select Color"
3134 };
3135
3136 int32_t toolbtn = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
3137 if(toolbtn > -1 && toolbtn < t_max)
3138 {
3139 int32_t column = toolbtn%tool_btns.w;
3140 int32_t row = toolbtn/tool_btns.w;
3141
3142 update_tooltip(temp_mouse_x,temp_mouse_y,tool_btns.x+(column*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale, toolnames[toolbtn]);
3143 redraw=true;
3144 }
3145 /* Highlight the hovered pixel? Eh, maybe too much?
3146 int32_t hov_pix = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3147 if(hov_pix > -1)
3148 {
3149 int32_t column = hov_pix%zoomtile.w;
3150 int32_t row = hov_pix/zoomtile.w;
3151
3152 update_tooltip(temp_mouse_x,temp_mouse_y,zoomtile.x+(column*zoomtile.xscale),zoomtile.y+(row*zoomtile.yscale),zoomtile.xscale,zoomtile.yscale, NULL);
3153 redraw=true;
3154 }*/
3155
3156 if(redraw)
3157 {
3158 custom_vsync();
3159 draw_edit_scr(tile,flip,cs,oldtile, false);
3160 }
3161 else
3162 {
3163 bool hs=has_selection();
3164
3165 if(hs)
3166 {
3167 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
3168 }
3169
3170 custom_vsync();
3171
3172 if(hs)
3173 {
3174 // blit(screen2, screen, 79, 31, 79, 31, 129, 129);
3175 blit(screen2, screen, zoomtile.x-1,zoomtile.y-1, zoomtile.x-1,zoomtile.y-1, (zoomtile.w*zoomtile.xscale)+1, (zoomtile.h*zoomtile.yscale)+1);
3176 }
3177
3178 update_tool_cursor();
3179 SCRFIX();
3180 }
3181
3182 }
3183 while(!done);
3184
3185 unfloat_selection();
3186 clear_selection_grid();
3187
3188 while(gui_mouse_b())
3189 {
3190 /* do nothing */
3191 rest(1);
3192 }
3193
3194 if(done==1)
3195 {
3196 for(int32_t i=0; i<undocount; i++)
3197 {
3198 newtilebuf[tile].data[i]=oldtile[i];
3199 }
3200 }
3201 else
3202 {
3203 byte *buf = new byte[undocount];
3204
3205 // put back old tile
3206 for(int32_t i=0; i<undocount; i++)
3207 {
3208 buf[i] = newtilebuf[tile].data[i];
3209 newtilebuf[tile].data[i] = oldtile[i];
3210 }
3211
3212 // go
3213 go_tiles();
3214
3215 // replace old tile with new one again
3216 for(int32_t i=0; i<undocount; i++)
3217 {
3218 newtilebuf[tile].data[i] = buf[i];
3219 }
3220
3221 // usetiles=true;
3222 saved=false;
3223
3224 if(buf!=NULL)
3225 {
3226 delete[] buf;
3227 }
3228 }
3229
3230 MouseSprite::set(ZQM_NORMAL);
3231 register_blank_tiles();
3232 register_used_tiles();
3233 clear_tooltip();
3234 comeback();
3235 destroy_bitmap(selection_pattern);
3236 destroy_bitmap(selecting_pattern);
3237 destroy_bitmap(intersection_pattern);
3238 font = oldfont;
3239 popup_zqdialog_end();
3240 }
3241
3242 /* Grab Tile Code */
3243
3244 enum recolorState { rcNone, rc4Bit, rc8Bit };
3245
3246 BITMAP* original_imagebuf_bitmap=NULL;
3247 void *imagebuf=NULL;
3248 int32_t imagebuf_bitmap_scale=0;
3249 #define IMAGEBUF_SCALE (imagebuf_bitmap_scale > 0 ? imagebuf_bitmap_scale : 1.0 / -imagebuf_bitmap_scale)
3250 int32_t imagesize=0;
3251 int32_t tilecount=0;
3252 int32_t imagetype=0;
3253 int32_t imagex,imagey,selx,sely;
3254 int32_t bp=4,grabmode=16,romofs=0,romtilemode=0, romtilecols=8;
3255 bool nesmode=false;
3256 int32_t grabmask=0;
3257 recolorState recolor=rcNone;
3258 PALETTE imagepal;
3259
3260 /* bestfit_color:
3261 * Searches a palette for the color closest to the requested R, G, B value.
3262 */
3263 int32_t bestfit_cset_color(int32_t cs, int32_t r, int32_t g, int32_t b)
3264 {
3265 int32_t bestMatch = 0; // Color with the lowest total difference so far
3266 float bestTotalDiff = 100000; // Total difference between requested color and bestMatch
3267 float bestHighDiff = 100000; // Greatest difference of R, G, B between requested color and bestMatch
3268
3269 for(int32_t i = 0; i < CSET_SIZE; i++)
3270 {
3271 byte *rgbByte;
3272
3273 // This seems to be right...
3274 if(cs==2 || cs==3 || cs==4)
3275 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + i) * 3;
3276 else if(cs==9)
3277 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + i) * 3;
3278 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3279 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + i) * 3;
3280 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3281 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + i) * 3;
3282 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3283 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + i) * 3;
3284 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3285 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + i) * 3;
3286 else
3287 rgbByte = colordata + (CSET(cs)+i)*3;
3288
3289 int32_t dr=r-*rgbByte;
3290 int32_t dg=g-*(rgbByte+1);
3291 int32_t db=b-*(rgbByte+2);
3292
3293 // Track both the total color difference and the single greatest
3294 // difference of R, G, B. The idea is that it's better to have
3295 // two or three small differences than one big one.
3296 // The differences are multiplied by different numbers to account
3297 // for the differences in perceived brightness of the three colors.
3298 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3299 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3300
3301 // Perfect match? Just stop here.
3302 if(totalDiff==0)
3303 return i;
3304
3305 if(totalDiff < bestTotalDiff || // Best match so far?
3306 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3307 {
3308 bestMatch=i;
3309 bestTotalDiff=totalDiff;
3310 bestHighDiff=highDiff;
3311 }
3312 }
3313
3314 return bestMatch;
3315 }
3316
3317 // Same as the above, but draws from all colors in CSets 0-11.
3318 int32_t bestfit_cset_color_8bit(int32_t r, int32_t g, int32_t b)
3319 {
3320 int32_t bestMatch = 0;
3321 float bestTotalDiff = 100000;
3322 float bestHighDiff = 100000;
3323
3324 for(int32_t i = 0; i < 192; i++) // 192 colors in CSets 0-11
3325 {
3326 byte *rgbByte;
3327
3328 int32_t cs=i>>4;
3329 if(cs==2 || cs==3 || cs==4)
3330 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + (i%16)) * 3;
3331 else if(cs==9)
3332 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + (i%16)) * 3;
3333 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3334 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + (i%16)) * 3;
3335 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3336 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + (i%16)) * 3;
3337 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3338 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + (i%16)) * 3;
3339 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3340 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + (i%16)) * 3;
3341 else
3342 rgbByte = colordata + i * 3;
3343
3344 int32_t dr=r-*rgbByte;
3345 int32_t dg=g-*(rgbByte+1);
3346 int32_t db=b-*(rgbByte+2);
3347
3348 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3349 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3350
3351 if(totalDiff==0) // Perfect match?
3352 return i;
3353
3354 if(totalDiff < bestTotalDiff || // Best match so far?
3355 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3356 {
3357 bestMatch=i;
3358 bestTotalDiff=totalDiff;
3359 bestHighDiff=highDiff;
3360 }
3361 }
3362
3363 return bestMatch;
3364 }
3365
3366 byte cset_reduce_table[PAL_SIZE];
3367
3368 void calc_cset_reduce_table(PALETTE pal, int32_t cs)
3369 {
3370 for(int32_t i=0; i<PAL_SIZE; i++)
3371 {
3372 cset_reduce_table[i]=(bestfit_cset_color(cs, pal[i].r, pal[i].g, pal[i].b)&0x0F);
3373 }
3374 }
3375
3376 void calc_cset_reduce_table_8bit(PALETTE pal)
3377 {
3378 for(int32_t i=0; i<PAL_SIZE; i++)
3379 {
3380 cset_reduce_table[i]=bestfit_cset_color_8bit(pal[i].r, pal[i].g, pal[i].b);
3381 }
3382 }
3383
3384 void puttileROM(BITMAP *dest,int32_t x,int32_t y,byte *src,int32_t cs)
3385 {
3386 //storage space for the grabbed image
3387 byte buf[64];
3388 memset(buf,0,64);
3389 byte *oldsrc=src;
3390
3391 //for 8 lines in the source image...
3392 for(int32_t line=0; line<(nesmode?4:8); line++)
3393 {
3394 //bx is the pixel at the start of a line in the storage buffer
3395 int32_t bx=line<<(nesmode?4:3);
3396 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3397 byte b=src[(bp&1)?line:line<<1];
3398
3399 //fill the storage buffer with data from the source image
3400 for(int32_t i=7; i>=0; --i)
3401 {
3402 buf[bx+i] = (b&1)+(cs<<4);
3403 b>>=1;
3404 }
3405 }
3406
3407 ++src;
3408
3409 for(int32_t p=1; p<bp; p++)
3410 {
3411 for(int32_t line=0; line<(nesmode?4:8); line++)
3412 {
3413 int32_t bx=line<<(nesmode?4:3);
3414 byte b=src[(bp&1)?line:line<<1];
3415
3416 for(int32_t i=7; i>=0; --i)
3417 {
3418 if(nesmode)
3419 {
3420 buf[bx+8+i] = (b&1)+(cs<<4);
3421 }
3422 else
3423 {
3424 buf[bx+i] |= (b&1)<<p;
3425 }
3426
3427 b>>=1;
3428 }
3429 }
3430
3431 if(p&1)
3432 {
3433 src+=15;
3434 }
3435 else
3436 {
3437 ++src;
3438 }
3439 }
3440
3441
3442 if(nesmode)
3443 {
3444 src=oldsrc;
3445
3446 for(int32_t counter=0; counter<2; ++counter, ++src)
3447 {
3448 //for 8 lines in the source image...
3449 for(int32_t line=0; line<4; line++)
3450 {
3451 //bx is the pixel at the start of a line in the storage buffer
3452 int32_t bx=line<<4;
3453 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3454 byte b=src[(line+4)<<1];
3455
3456 //fill the storage buffer with data from the source image
3457 for(int32_t i=7; i>=0; --i)
3458 {
3459 // buf[bx+i] = (b&1)+(cs<<4);
3460 buf[bx+(counter<<3)+i] |= (b&1)<<1;
3461 b>>=1;
3462 }
3463 }
3464 }
3465 }
3466
3467 int32_t c=0;
3468
3469 switch(romtilemode)
3470 {
3471 case 0:
3472 case 1:
3473 case 2:
3474 for(int32_t j=0; j<8; j++)
3475 {
3476 for(int32_t i=0; i<8; i++)
3477 {
3478 putpixel(dest,x+i,y+j,buf[c++]);
3479 }
3480 }
3481
3482 break;
3483
3484 case 3:
3485 for(int32_t j=0; j<4; j++)
3486 {
3487 for(int32_t i=0; i<16; i++)
3488 {
3489 putpixel(dest,x+i,y+j,buf[c++]);
3490 }
3491 }
3492
3493 break;
3494 }
3495 }
3496
3497 const char *file_type[ftMAX]=
3498 {
3499 "None", "BIN", "BMP", "TIL", "ZGP", "QSU", "ZQT", "QST"
3500 };
3501
3502 void draw_grab_window()
3503 {
3504 int w = 640;
3505 int h = 480;
3506 int window_xofs=0;//(zq_screen_w-w-12)>>1;
3507 int window_yofs=0;//(zq_screen_h-h-25-6)>>1;
3508 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
3509 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+2+2-(79*2), FR_DEEP);
3510
3511 FONT *oldfont = font;
3512 font = get_zc_font(font_lfont);
3513 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Grab Tile(s)", true);
3514 font=oldfont;
3515 }
3516
3517 void draw_grab_scr(int32_t tile,int32_t cs,byte *newtile,int32_t black,int32_t white, int32_t width, int32_t height, byte *newformat)
3518 {
3519 width=width;
3520 height=height;
3521 white=white; // happy birthday compiler
3522
3523 int32_t yofs=0;
3524 //clear_to_color(screen2,bg);
3525 rectfill(screen2, 0, 0, 319, 159, black);
3526 rectfill(screen2,0,162,319,239,jwin_pal[jcBOX]);
3527 _allegro_hline(screen2, 0, 160, 319, jwin_pal[jcMEDLT]);
3528 _allegro_hline(screen2, 0, 161, 319, jwin_pal[jcLIGHT]);
3529 yofs=3;
3530
3531 // text_mode(-1);
3532 int32_t tileromcolumns=20;
3533
3534 switch(imagetype)
3535 {
3536 case ftBMP:
3537 if(recolor==rcNone)
3538 {
3539 blit((BITMAP*)imagebuf,screen2,imagex<<4,imagey<<4,0,0,320,160);
3540 }
3541 else
3542 {
3543 int32_t maxy=zc_min(160,((BITMAP*)imagebuf)->h);
3544 int32_t maxx=zc_min(320,((BITMAP*)imagebuf)->w);
3545
3546 for(int32_t y=0; y<maxy; y++)
3547 {
3548 if((imagey<<4)+y>=((BITMAP*)imagebuf)->h)
3549 {
3550 break;
3551 }
3552
3553 for(int32_t x=0; x<maxx; x++)
3554 {
3555 if((imagex<<4)+x>=((BITMAP*)imagebuf)->w)
3556 {
3557 break;
3558 }
3559
3560 if(recolor==rc8Bit)
3561 screen2->line[y][x]=cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]];
3562 else
3563 screen2->line[y][x]=(cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]])+(cs<<4);
3564 }
3565 }
3566 }
3567
3568 break;
3569
3570 case ftZGP:
3571 case ftQST:
3572 case ftZQT:
3573 case ftQSU:
3574 case ftTIL:
3575 {
3576 tiledata *hold = newtilebuf;
3577 newtilebuf = grabtilebuf;
3578 //fixme
3579 imagey = vbound(imagey, 0, MAXTILEROWS); //fixed -Z This can no longer crash if you scroll past the end of the tile pages. 6th June, 2020
3580 int32_t t=imagey*TILES_PER_ROW;
3581
3582 for(int32_t i=0; i<200; i++) // 10 rows, down to y=160
3583 {
3584 if(t <= tilecount)
3585 {
3586 puttile16(screen2,t,(i%TILES_PER_ROW)<<4,(i/TILES_PER_ROW)<<4,cs,0);
3587 }
3588
3589 ++t;
3590 }
3591
3592 newtilebuf = hold;
3593 //fixme
3594 }
3595 break;
3596
3597 case ftBIN:
3598 {
3599 int32_t ofs = (tileromcolumns*imagex + imagey) * 128*bp + romofs;
3600 byte *buf = (byte*)imagebuf;
3601
3602 switch(romtilemode)
3603 {
3604 case 0:
3605 for(int32_t y=0; y<160; y+=8)
3606 {
3607 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3608 {
3609 puttileROM(screen2,x,y,buf+ofs,cs);
3610 ofs+=8*bp;
3611 }
3612 }
3613
3614 for(int32_t y=0; y<160; y+=8)
3615 {
3616 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3617 {
3618 puttileROM(screen2,x+128,y,buf+ofs,cs);
3619 ofs+=8*bp;
3620 }
3621 }
3622
3623 break;
3624
3625 case 1:
3626 for(int32_t y=0; y<160; y+=16)
3627 {
3628 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3629 {
3630 puttileROM(screen2,x,y,buf+ofs,cs);
3631 ofs+=8*bp;
3632 puttileROM(screen2,x,y+8,buf+ofs,cs);
3633 ofs+=8*bp;
3634 }
3635 }
3636
3637 for(int32_t y=0; y<160; y+=16)
3638 {
3639 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3640 {
3641 puttileROM(screen2,x+128,y,buf+ofs,cs);
3642 ofs+=8*bp;
3643 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3644 ofs+=8*bp;
3645 }
3646 }
3647
3648 break;
3649
3650 case 2:
3651 for(int32_t y=0; y<160; y+=16)
3652 {
3653 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3654 {
3655 puttileROM(screen2,x,y,buf+ofs,cs);
3656 ofs+=8*bp;
3657 puttileROM(screen2,x+8,y,buf+ofs,cs);
3658 ofs+=8*bp;
3659 puttileROM(screen2,x,y+8,buf+ofs,cs);
3660 ofs+=8*bp;
3661 puttileROM(screen2,x+8,y+8,buf+ofs,cs);
3662 ofs+=8*bp;
3663 }
3664 }
3665
3666 for(int32_t y=0; y<160; y+=16)
3667 {
3668 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3669 {
3670 puttileROM(screen2,x+128,y,buf+ofs,cs);
3671 ofs+=8*bp;
3672 puttileROM(screen2,x+136,y,buf+ofs,cs);
3673 ofs+=8*bp;
3674 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3675 ofs+=8*bp;
3676 puttileROM(screen2,x+136,y+8,buf+ofs,cs);
3677 ofs+=8*bp;
3678 }
3679 }
3680
3681 break;
3682
3683 case 3:
3684 for(int32_t y=0; y<160; y+=16)
3685 {
3686 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3687 {
3688 puttileROM(screen2,x,y,buf+ofs,cs);
3689 ofs+=8*bp;
3690 puttileROM(screen2,x,y+4,buf+ofs,cs);
3691 ofs+=8*bp;
3692 puttileROM(screen2,x,y+8,buf+ofs,cs);
3693 ofs+=8*bp;
3694 puttileROM(screen2,x,y+12,buf+ofs,cs);
3695 ofs+=8*bp;
3696 }
3697 }
3698
3699 for(int32_t y=0; y<160; y+=16)
3700 {
3701 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3702 {
3703 puttileROM(screen2,x+128,y,buf+ofs,cs);
3704 ofs+=8*bp;
3705 puttileROM(screen2,x+128,y+4,buf+ofs,cs);
3706 ofs+=8*bp;
3707 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3708 ofs+=8*bp;
3709 puttileROM(screen2,x+128,y+12,buf+ofs,cs);
3710 ofs+=8*bp;
3711 }
3712 }
3713
3714 break;
3715 }
3716 }
3717 break;
3718 }
3719
3720 tiledata hold;
3721 bool holdblank = blank_tile_table[0];
3722
3723 if(is_valid_format(newtilebuf[0].format))
3724 {
3725 hold.format = newtilebuf[0].format;
3726 hold.data = (byte *)malloc(tilesize(hold.format));
3727 memcpy(hold.data, newtilebuf[0].data, tilesize(hold.format));
3728 }
3729 else
3730 {
3731 hold.format=tfInvalid;
3732 hold.data=NULL;
3733 }
3734
3735 newtilebuf[0].format=newformat[0];
3736 blank_tile_table[0] = false;
3737
3738 if(newtilebuf[0].data!=NULL)
3739 {
3740 free(newtilebuf[0].data);
3741 }
3742
3743 if(is_valid_format(newtilebuf[0].format))
3744 {
3745 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3746
3747 for(int32_t i=0; i<tilesize(newtilebuf[0].format); i++)
3748 {
3749 newtilebuf[0].data[i]=newtile[i];
3750 }
3751 }
3752 else
3753 {
3754 newtilebuf[0].data=NULL;
3755 }
3756
3757 puttile16(screen2,0,208,168+yofs,cs,0);
3758 overtile16(screen2,0,232,168+yofs,cs,0);
3759 newtilebuf[0].format=hold.format;
3760 blank_tile_table[0] = holdblank;
3761
3762 if(newtilebuf[0].data!=NULL)
3763 {
3764 free(newtilebuf[0].data);
3765 }
3766
3767 if(is_valid_format(newtilebuf[0].format))
3768 {
3769 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3770
3771 for(int32_t i=0; i<256; i++)
3772 {
3773 newtilebuf[0].data[i]=hold.data[i];
3774 }
3775 }
3776 else
3777 {
3778 newtilebuf[0].data=NULL;
3779 }
3780
3781 if(hold.data!=NULL)
3782 {
3783 free(hold.data);
3784 }
3785
3786 puttile16(screen2,tile,208,192+yofs,cs,0);
3787 overtile16(screen2,tile,232,192+yofs,cs,0);
3788
3789 rectfill(screen2,184,168+yofs,191,175+yofs,grabmask&1?vc(12):vc(7));
3790 rectfill(screen2,192,168+yofs,199,175+yofs,grabmask&2?vc(12):vc(7));
3791 rectfill(screen2,184,176+yofs,191,183+yofs,grabmask&4?vc(12):vc(7));
3792 rectfill(screen2,192,176+yofs,199,183+yofs,grabmask&8?vc(12):vc(7));
3793
3794 // rect(screen2,183,167,200,184,dvc(7*2));
3795 // rect(screen2,207,167,224,184,dvc(7*2));
3796 // rect(screen2,231,167,248,184,dvc(7*2));
3797 // rect(screen2,207,191,224,208,dvc(7*2));
3798 // rect(screen2,231,191,248,208,dvc(7*2));
3799
3800 /*
3801 rect(screen2,183,167,200,184,vc(14));
3802 rect(screen2,207,167,224,184,vc(14));
3803 rect(screen2,231,167,248,184,vc(14));
3804 rect(screen2,207,191,224,208,vc(14));
3805 rect(screen2,231,191,248,208,vc(14));
3806 */
3807 jwin_draw_frame(screen2,182,166+yofs,20,20,FR_DEEP);
3808 jwin_draw_frame(screen2,206,166+yofs,20,20,FR_DEEP);
3809 jwin_draw_frame(screen2,230,166+yofs,20,20,FR_DEEP);
3810 jwin_draw_frame(screen2,206,190+yofs,20,20,FR_DEEP);
3811 jwin_draw_frame(screen2,230,190+yofs,20,20,FR_DEEP);
3812 int32_t screen_xofs=6;
3813 int32_t screen_yofs=25;
3814 int winh = 511;
3815 int32_t mul = 2;
3816
3817 yofs=16;
3818
3819 custom_vsync();
3820
3821 stretch_blit(screen2,screen,0,0,320,240,screen_xofs,screen_yofs,640,480);
3822
3823 // Suspend the current font while draw_text_button does its work
3824 FONT* oldfont = font;
3825
3826 font = get_zc_font(font_lfont_l);
3827
3828 int txt_x = 8*mul;
3829 int rbtn_x = 255*mul;
3830 int max_fpath_wid = rbtn_x-2-txt_x;
3831 int max_fpath_wid2 = max_fpath_wid-text_length(font,"... ");
3832 // Interface
3833 switch(imagetype)
3834 {
3835 case 0:
3836 textprintf_ex(screen,font,txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s",imgstr[imagetype]);
3837 break;
3838
3839 case ftBMP:
3840 {
3841 std::string text = fmt::format("{} {}x{}, {:.2g}x zoom with , and .", imgstr[imagetype], original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, IMAGEBUF_SCALE);
3842 int text_x = txt_x;
3843 int text_y = (216 + yofs) * mul;
3844 // TODO: can almost use this, but drawing is offset. prob cuz drawing to a different bitmap than the normal screen bitmap? idk
3845 // int text_w = text_length(font, text.c_str());
3846 // int text_h = text_height(font);
3847 // static int grab_scale_tooltip_id = ttip_register_id();
3848 // ttip_install(grab_scale_tooltip_id, "zoom with , and .", text_x, text_y, text_w, text_h, text_x, text_y - 40);
3849 textprintf_ex(screen, font, text_x, text_y, jwin_pal[jcTEXTFG], jwin_pal[jcBOX], "%s", text.c_str());
3850
3851 draw_text_button(screen,117*mul,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Recolor",vc(1),vc(14),0,true);
3852 break;
3853 }
3854
3855 case ftZGP:
3856 case ftQST:
3857 case ftZQT:
3858 case ftQSU:
3859 case ftTIL:
3860 case ftBIN:
3861 textprintf_ex(screen,get_zc_font(font_lfont_l),txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s %d KB",imgstr[imagetype],imagesize>>10);
3862 break;
3863 }
3864
3865 textprintf_ex(screen,font,txt_x,(168+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"sel: %d %d",selx,sely);
3866 textprintf_ex(screen,font,txt_x,(176+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"pos: %d %d",imagex,imagey);
3867
3868 if(bp==8)
3869 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"8-bit");
3870 else
3871 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"cset: %d",cs);
3872 textprintf_ex(screen,font,txt_x,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"step: %d",grabmode);
3873
3874 if(imagetype==ftBIN)
3875 {
3876 textprintf_ex(screen,font,104*mul,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"bp: %d%s",bp,nesmode?" (NES)":"");
3877 textprintf_ex(screen,font,104*mul,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"ofs: %Xh",romofs);
3878 textprintf_ex(screen,font,104*mul,(208+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"m: %d",romtilemode);
3879 }
3880
3881 int fpath_y = (224+yofs)*mul;
3882 if(text_length(font,imagepath) <= max_fpath_wid)
3883 textout_ex(screen,font,imagepath,txt_x,fpath_y,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3884 else
3885 {
3886 char buf[2052] = {0};
3887 strncpy(buf,imagepath,2048);
3888 int len = strlen(buf);
3889 char *ptr = buf;
3890 char *endptr = buf+len;
3891 char *it = endptr;
3892 int tmpy = fpath_y;
3893 int tmph = text_height(font)+1;
3894 while(true)
3895 {
3896 if(tmpy+tmph > (winh-2))
3897 break; //Out of space!
3898 char c = *it;
3899 bool end = !c;
3900 *it = 0;
3901 int newlen = text_length(font,ptr);
3902 if(newlen <= (end ? max_fpath_wid : max_fpath_wid2))
3903 {
3904 if(end) //No stored character, string ended
3905 {
3906 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3907 break;
3908 }
3909 char t[5];
3910 t[0] = c;
3911 for(int q = 1; q < 5; ++q)
3912 t[q] = it[q];
3913 strcpy(it,"...");
3914 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3915 for(int q = 0; q < 5; ++q)
3916 it[q] = t[q];
3917 tmpy += tmph;
3918 ptr = it;
3919 it = endptr;
3920 }
3921 else
3922 {
3923 *it = c;
3924 --it;
3925 }
3926 }
3927 }
3928 draw_text_button(screen,rbtn_x,(168+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"OK",vc(1),vc(14),0,true);
3929 draw_text_button(screen,rbtn_x,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Cancel",vc(1),vc(14),0,true);
3930 draw_text_button(screen,rbtn_x,(216+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"File",vc(1),vc(14),0,true);
3931 draw_text_button(screen,117*mul,(166+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Leech",vc(1),vc(14),0,true);
3932
3933 //int32_t rectw = 16*mul;
3934 //rect(screen,selx+screen_xofs,sely+screen_yofs,selx+screen_xofs+((width-1)*rectw)+rectw-1,sely+screen_yofs+((height-1)*rectw)+rectw-1,white);
3935 SCRFIX();
3936 font = oldfont;
3937 }
3938
3939 RGB_MAP rgb_table;
3940 COLOR_MAP imagepal_table;
3941
3942
3943 extern void return_RAMpal_color(AL_CONST PALETTE pal, int32_t x, int32_t y, RGB *rgb)
3944 {
3945 //these are here to bypass compiler warnings about unused arguments
3946 x=x;
3947
3948 rgb->r = pal[y].r;
3949 rgb->g = pal[y].g;
3950 rgb->b = pal[y].b;
3951 }
3952
3953
3954 void load_imagebuf()
3955 {
3956 PACKFILE *f;
3957 //cache QRS
3958 //byte cached_rules[QUESTRULES_NEW_SIZE] = { 0 };
3959 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
3960 // {
3961 // cached_rules[q] = quest_rules[q];
3962 // }
3963 bool compressed=false;
3964 bool encrypted=false;
3965 tiledata *hold=newtilebuf;
3966 zquestheader tempheader;
3967 memset(&tempheader, 0, sizeof(zquestheader));
3968
3969 if(imagebuf)
3970 {
3971 switch(imagetype)
3972 {
3973 case ftBMP:
3974 if (original_imagebuf_bitmap != imagebuf)
3975 destroy_bitmap((BITMAP*)imagebuf);
3976 destroy_bitmap(original_imagebuf_bitmap);
3977 break;
3978
3979 case ftZGP:
3980 case ftQST:
3981 case ftZQT:
3982 case ftQSU:
3983 case ftTIL:
3984 clear_tiles(grabtilebuf);
3985 break;
3986
3987 case ftBIN:
3988 free(imagebuf);
3989 break;
3990 }
3991
3992 imagebuf=NULL;
3993 original_imagebuf_bitmap=NULL;
3994 }
3995
3996 selx=sely=romofs=0;
3997 bp=4;
3998 imagetype=filetype(imagepath);
3999
4000 dword section_id;
4001 dword section_version;
4002 dword section_cversion;
4003
4004 switch(imagetype)
4005 {
4006 case ftBMP:
4007 packfile_password("");
4008 memset(imagepal, 0, sizeof(PALETTE));
4009 original_imagebuf_bitmap = load_bitmap(imagepath,imagepal);
4010 imagesize = file_size_ex_password(imagepath,"");
4011 tilecount=0;
4012 create_rgb_table(&rgb_table, imagepal, NULL);
4013 rgb_map = &rgb_table;
4014 create_color_table(&imagepal_table, RAMpal, return_RAMpal_color, NULL);
4015
4016 if(!original_imagebuf_bitmap)
4017 {
4018 imagetype=0;
4019 }
4020 else
4021 {
4022 imagebuf = original_imagebuf_bitmap;
4023 imagebuf_bitmap_scale = 1;
4024 }
4025
4026 break;
4027
4028 case ftBIN:
4029 packfile_password("");
4030 imagesize = file_size_ex_password(imagepath, "");
4031 tilecount=0;
4032
4033 if(imagesize)
4034 {
4035 imagebuf = malloc(imagesize);
4036
4037 if(!readfile(imagepath,imagebuf,imagesize))
4038 {
4039 free(imagebuf);
4040 imagesize=0;
4041 imagetype=0;
4042 }
4043 }
4044
4045 break;
4046
4047 case ftTIL:
4048 packfile_password("");
4049 imagesize = file_size_ex_password(imagepath,"");
4050 f = pack_fopen_password(imagepath,F_READ,"");
4051
4052 if(!f)
4053 {
4054 goto error;
4055 }
4056
4057 if(!p_mgetl(&section_id,f))
4058 {
4059 goto error;
4060 }
4061
4062 if(section_id==ID_TILES)
4063 {
4064 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)==0)
4065 {
4066 goto error;
4067 }
4068 }
4069
4070 error:
4071 pack_fclose(f);
4072 tilecount=count_tiles(grabtilebuf);
4073 break;
4074
4075 case ftZGP:
4076 packfile_password("");
4077 imagesize = file_size_ex_password(imagepath, "");
4078 f=pack_fopen_password(imagepath,F_READ,"");
4079
4080 if(!f)
4081 {
4082 goto error2;
4083 }
4084
4085 if(!p_mgetl(&section_id,f))
4086 {
4087 goto error2;
4088 }
4089
4090 if(section_id!=ID_GRAPHICSPACK)
4091 {
4092 goto error2;
4093 }
4094
4095 //section version info
4096 if(!p_igetw(&section_version,f))
4097 {
4098 goto error2;
4099 }
4100
4101 if(!p_igetw(&section_cversion,f))
4102 {
4103 goto error2;
4104 }
4105
4106 //tiles
4107 if(!p_mgetl(&section_id,f))
4108 {
4109 goto error2;
4110 }
4111
4112 if(section_id==ID_TILES)
4113 {
4114 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)!=0)
4115 {
4116 goto error2;
4117 }
4118 }
4119
4120 error2:
4121 pack_fclose(f);
4122 tilecount=count_tiles(grabtilebuf);
4123 break;
4124
4125 case ftQST:
4126 encrypted=true;
4127 case ftZQT:
4128 compressed=true;
4129 case ftQSU:
4130 packfile_password("");
4131 imagesize = file_size_ex_password(imagepath, encrypted ? datapwd : "");
4132 newtilebuf=grabtilebuf;
4133 byte skip_flags[4];
4134
4135 for(int32_t i=0; i<skip_max; ++i)
4136 {
4137 set_bit(skip_flags,i,1);
4138 }
4139
4140 set_bit(skip_flags,skip_tiles,0);
4141 set_bit(skip_flags,skip_header,0);
4142 int ret = loadquest(imagepath,&tempheader,&QMisc,customtunes,true,skip_flags);
4143 if (ret)
4144 {
4145 imagetype=0;
4146 imagesize=0;
4147 clear_tiles(grabtilebuf);
4148 chop_path(imagepath);
4149 }
4150
4151 if (!ret && encrypted && compressed)
4152 {
4153 if(quest_access(imagepath, &tempheader) != 1)
4154 {
4155 imagetype=0;
4156 imagesize=0;
4157 clear_tiles(grabtilebuf);
4158 chop_path(imagepath);
4159 }
4160 }
4161
4162 //setPackfilePassword(NULL);
4163 newtilebuf=hold;
4164 tilecount=count_tiles(grabtilebuf);
4165 break;
4166 }
4167
4168 rgb_map = &zq_rgb_table;
4169 //restore cashed QRs / rules
4170
4171 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
4172 // {
4173 // quest_rules[q] = cached_rules[q];
4174 // }
4175 }
4176
4177 static char bitstrbuf[32];
4178 bool leeching_from_tiles=false;
4179
4180 const char *bitlist(int32_t index, int32_t *list_size)
4181 {
4182 int32_t imported=2;
4183
4184 if(index>=0)
4185 {
4186 bound(index,0,leeching_from_tiles?2:1);
4187
4188 if(index==imported)
4189 {
4190 sprintf(bitstrbuf,"Imported");
4191 }
4192 else
4193 {
4194 sprintf(bitstrbuf,"%d",4<<index);
4195 }
4196
4197 return bitstrbuf;
4198 }
4199
4200 *list_size=leeching_from_tiles?3:2;
4201 return NULL;
4202 }
4203
4204 9 static ListData bit_list(bitlist, &font);
4205
4206 static DIALOG leech_dlg[] =
4207 {
4208 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
4209 9 { jwin_win_proc, 8, 20-4, 303+1, 216-42+1, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Leech Options", NULL, NULL },
4210 9 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
4211 // 2
4212 9 { jwin_button_proc, 180, 210-42-4, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
4213 9 { jwin_button_proc, 80, 210-42-4, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
4214 9 { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL },
4215 // 5
4216 9 { jwin_text_proc, 14, 49-4, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Update Status Every: ", NULL, NULL },
4217 9 { jwin_edit_proc, 114, 45-4, 36, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL },
4218 9 { jwin_radio_proc, 155, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Tiles", NULL, NULL },
4219 9 { jwin_radio_proc, 200, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Seconds", NULL, NULL },
4220 //9
4221 9 { jwin_frame_proc, 14, 63-2, 176+70, 50+30, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL },
4222 9 { jwin_text_proc, 14+8, 60-2, 80, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) " Duplicates ", NULL, NULL },
4223
4224 9 { jwin_check_proc, 20, 70, 168, 8+1, vc(15), vc(1), 0, 0, 1, 0, (void *) "Only check new tiles", NULL, NULL },
4225 9 { jwin_text_proc, 20, 90, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Normal:", NULL, NULL },
4226 9 { jwin_text_proc, 20, 100, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal Flip:", NULL, NULL },
4227 9 { jwin_text_proc, 20, 110, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Vertical Flip:", NULL, NULL },
4228 9 { jwin_text_proc, 20, 120, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal/Vertical Flip:", NULL, NULL },
4229 //16
4230 9 { jwin_radio_proc, 144, 90, 64+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4231 9 { jwin_radio_proc, 184, 90, 56+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4232 9 { jwin_radio_proc, 224, 90, 72+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4233
4234 9 { jwin_radio_proc, 144, 100, 64+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4235 9 { jwin_radio_proc, 184, 100, 56+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4236 9 { jwin_radio_proc, 224, 100, 72+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4237
4238 9 { jwin_radio_proc, 144, 110, 64+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4239 9 { jwin_radio_proc, 184, 110, 56+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4240 9 { jwin_radio_proc, 224, 110, 72+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4241
4242 9 { jwin_radio_proc, 144, 120, 64+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4243 9 { jwin_radio_proc, 184, 120, 56+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4244 9 { jwin_radio_proc, 224, 120, 72+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4245
4246 9 { jwin_ctext_proc, 144+4, 80, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Ignore", NULL, NULL },
4247 9 { jwin_ctext_proc, 184+4, 80, 56+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Check", NULL, NULL },
4248 9 { jwin_ctext_proc, 224+4, 80, 72+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Discard", NULL, NULL },
4249 9 { jwin_droplist_proc, 76, 145, 80, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &bit_list, NULL, NULL },
4250 9 { jwin_text_proc, 14, 149, 60, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Color Depth: ", NULL, NULL },
4251 9 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
4252 };
4253
4254 bool leech_tiles(tiledata *dest,int32_t start,int32_t cs)
4255 {
4256 bool shift=true; // fix this!
4257 int32_t cst=0;
4258 int32_t currtile=start;
4259 int32_t height=0, width=0;
4260 byte *testtile = new byte[tilesize(tf32Bit)];
4261 byte imported_format=0;
4262 char updatestring[6];
4263 bool canadd;
4264 bool temp_canadd;
4265 bool duplicate;
4266 int32_t total_duplicates_found=0, total_duplicates_discarded=0;
4267 int32_t duplicates_found[4]= //, duplicates_discarded[4]={0,0,0,0};
4268 {
4269 0,0,0,0
4270 };
4271 BITMAP *status;
4272 status = create_bitmap_ex(8,240,140);
4273 clear_bitmap(status);
4274 sprintf(updatestring, "%d", LeechUpdate);
4275 leech_dlg[0].dp2=get_zc_font(font_lfont);
4276 leech_dlg[6].dp=updatestring;
4277
4278 leech_dlg[10].flags=(OnlyCheckNewTilesForDuplicates!=0) ? D_SELECTED : 0;
4279
4280 for(int32_t i=0; i<2; i++)
4281 {
4282 leech_dlg[i+7].flags=0;
4283 }
4284
4285 leech_dlg[7+((LeechUpdateTiles==0) ? 1 : 0)].flags=D_SELECTED;
4286
4287 for(int32_t i=0; i<12; i++)
4288 {
4289 leech_dlg[i+16].flags=0;
4290 }
4291
4292 for(int32_t i=0; i<4; i++)
4293 {
4294 leech_dlg[(DuplicateAction[i])+16+(i*3)].flags=D_SELECTED;
4295 }
4296
4297 leech_dlg[31].d1=0;
4298
4299 large_dialog(leech_dlg);
4300
4301 int32_t ret = do_zqdialog(leech_dlg,3);
4302
4303 if(ret==2)
4304 {
4305 delete[] testtile;
4306 return false;
4307 }
4308
4309 int32_t cdepth=leech_dlg[31].d1+1;
4310 int32_t newformat=0;
4311 auto lu = atoi(updatestring);
4312 auto lut = (leech_dlg[7].flags&D_SELECTED)?1:0;
4313 if(LeechUpdate!=lu)
4314 {
4315 LeechUpdate=lu;
4316 zc_set_config("zquest","leech_update",LeechUpdate);
4317 }
4318 if(LeechUpdateTiles!=lut)
4319 {
4320 LeechUpdateTiles=lut;
4321 zc_set_config("zquest","leech_update_tiles",LeechUpdateTiles);
4322 }
4323
4324 int32_t old_dupe[4];
4325 for(int32_t j=0; j<4; j++)
4326 {
4327 old_dupe[j] = DuplicateAction[j];
4328 for(int32_t i=0; i<3; i++)
4329 {
4330 if(leech_dlg[i+16+(j*3)].flags&D_SELECTED)
4331 {
4332 DuplicateAction[j]=i;
4333 }
4334 }
4335 }
4336 if(old_dupe[0] != DuplicateAction[0])
4337 zc_set_config("zquest","normal_duplicate_action",DuplicateAction[0]);
4338 if(old_dupe[1] != DuplicateAction[1])
4339 zc_set_config("zquest","horizontal_duplicate_action",DuplicateAction[1]);
4340 if(old_dupe[2] != DuplicateAction[2])
4341 zc_set_config("zquest","vertical_duplicate_action",DuplicateAction[2]);
4342 if(old_dupe[3] != DuplicateAction[3])
4343 zc_set_config("zquest","both_duplicate_action",DuplicateAction[3]);
4344
4345 auto ocntfd = leech_dlg[10].flags&D_SELECTED?1:0;
4346 if(OnlyCheckNewTilesForDuplicates!=ocntfd)
4347 {
4348 OnlyCheckNewTilesForDuplicates=ocntfd;
4349 zc_set_config("zquest","only_check_new_tiles_for_duplicates",ocntfd);
4350 }
4351
4352 leeching_from_tiles=false;
4353
4354 switch(imagetype)
4355 {
4356 case ftBIN:
4357 width=imagesize/128;
4358 height=1;
4359 break;
4360
4361 case ftZGP:
4362 case ftQST:
4363 case ftZQT:
4364 case ftQSU:
4365 case ftTIL:
4366 leeching_from_tiles=true;
4367 width=count_tiles(grabtilebuf);
4368 height=1;
4369 break;
4370
4371 case ftBMP:
4372 width=((((BITMAP*)imagebuf)->w)+15)/16;
4373 height=((((BITMAP*)imagebuf)->h)+15)/16;
4374 break;
4375 }
4376
4377 if(currtile+(width*height)>NEWMAXTILES)
4378 {
4379 if(jwin_alert("Confirm Truncation","Too many tiles.","Truncation may occur.",NULL,"&OK","&Cancel",'o','c',get_zc_font(font_lfont))==2)
4380 {
4381 delete[] testtile;
4382 return false;
4383 }
4384 }
4385
4386 go_tiles();
4387 saved=false;
4388
4389 // usetiles=true;
4390 for(int32_t ty=0; ty<height; ty++) //for every row
4391 {
4392 for(int32_t tx=0; tx<width; tx++) //for every column (tile)
4393 {
4394 if((((ty*width)+tx)%zc_max(LeechUpdate, 1))==0) //update status
4395 {
4396 FONT *oldfont = font;
4397 static BITMAP *tbar = create_bitmap_ex(8,240-6, 18);
4398 static bool created_tbar=false;
4399 jwin_draw_win(status, 0, 0, 240, 140, FR_WIN);
4400
4401 if(created_tbar)
4402 {
4403 blit(tbar, status, 0, 0, 3, 3, 240-6, 18);
4404 }
4405 else
4406 {
4407 font = get_zc_font(font_lfont);
4408 jwin_draw_titlebar(tbar, 0, 0, 240-6, 18, "Leech Status", false);
4409 font = oldfont;
4410 created_tbar=true;
4411 blit(tbar, status, 0, 0, 3, 3, 320-6, 18);
4412 }
4413
4414 textprintf_centre_ex(status,font,120,24,jwin_pal[jcTEXTFG],-1,"Checking %d of %d",((ty*width)+tx), (width*height));
4415 textprintf_centre_ex(status,font,120,34,jwin_pal[jcTEXTFG],-1,"%d tiles imported",currtile-start);
4416 jwin_draw_frame(status, 40, 49, 160, 70, FR_ETCHED);
4417 textprintf_centre_ex(status,font,120,46,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]," Duplicates ");
4418 textprintf_centre_ex(status,font,120,56,jwin_pal[jcTEXTFG],-1,"%d/%d found/discarded",total_duplicates_found, total_duplicates_discarded);
4419 textprintf_centre_ex(status,font,120,76,jwin_pal[jcTEXTFG],-1,"%d normal %s",duplicates_found[0],((DuplicateAction[0]<2)?"found":"discarded"));
4420 textprintf_centre_ex(status,font,120,86,jwin_pal[jcTEXTFG],-1,"%d flipped (h) %s",duplicates_found[1],((DuplicateAction[1]<2)?"found":"discarded"));
4421 textprintf_centre_ex(status,font,120,96,jwin_pal[jcTEXTFG],-1,"%d flipped (v) %s",duplicates_found[2],((DuplicateAction[2]<2)?"found":"discarded"));
4422 textprintf_centre_ex(status,font,120,106,jwin_pal[jcTEXTFG],-1,"%d flipped (hv) %s",duplicates_found[3],((DuplicateAction[3]<2)?"found":"discarded"));
4423 textprintf_centre_ex(status,font,120,128,jwin_pal[jcTEXTFG],-1,"Press any key to stop.");
4424 blit(status,screen,0, 0, 40, 20, 240, 140);
4425 SCRFIX();
4426 }
4427
4428 canadd=true;
4429
4430 if(currtile>=NEWMAXTILES) //if we've maxed out on our tiles...
4431 {
4432 delete[] testtile;
4433 return true;
4434 }
4435
4436 switch(imagetype)
4437 {
4438 case ftBIN:
4439 break;
4440
4441 case ftZGP:
4442 case ftQST:
4443 case ftZQT:
4444 case ftQSU:
4445 case ftTIL:
4446 memset(testtile, 0, tilesize(tf32Bit));
4447 imported_format=grabtilebuf[tx].format;
4448
4449 switch(cdepth)
4450 {
4451 case 1: //4-bit
4452 newformat=tf4Bit;
4453
4454 switch(imported_format)
4455 {
4456 case tf4Bit:
4457 case tf8Bit:
4458 for(int32_t y=0; y<16; y++) //snag a tile
4459 {
4460 for(int32_t x=0; x<16; x+=2)
4461 {
4462 testtile[(y*8)+(x/2)]=
4463 (grabtilebuf[tx].data[y*16+x]&15)+
4464 ((grabtilebuf[tx].data[y*16+x+1]&15)<<4);
4465 }
4466 }
4467
4468 break;
4469 }
4470
4471 break;
4472
4473 case 2: //8-bit
4474 newformat=tf8Bit;
4475
4476 switch(imported_format)
4477 {
4478 case tf4Bit:
4479 unpack_tile(grabtilebuf, tx, 0, true);
4480 cst = cs&15;
4481 cst <<= CSET_SHFT;
4482
4483 for(int32_t i=0; i<256; i++)
4484 {
4485 if(!shift||unpackbuf[i]!=0)
4486 {
4487 unpackbuf[i]+=cst;
4488 }
4489 }
4490
4491 pack_tiledata(testtile, unpackbuf, tf8Bit);
4492 break;
4493
4494 case tf8Bit:
4495 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4496 break;
4497 }
4498
4499 break;
4500
4501 case 3: //original tile's bit depth
4502 newformat=imported_format;
4503 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4504 break;
4505 }
4506
4507 break;
4508
4509 case ftBMP:
4510 newformat=cdepth;
4511
4512 for(int32_t y=0; y<16; y++) //snag a tile
4513 {
4514 for(int32_t x=0; x<16; x+=2)
4515 {
4516 testtile[(y*16)+x]=getpixel(((BITMAP*)imagebuf),(tx*16)+x,(ty*16)+y);
4517 testtile[(y*16)+x+1]=getpixel(((BITMAP*)imagebuf),(tx*16)+x+1,(ty*16)+y);
4518 }
4519 }
4520
4521 break;
4522 }
4523
4524 if(DuplicateAction[0]+DuplicateAction[1]+DuplicateAction[2]+DuplicateAction[3]>0)
4525 {
4526 temp_canadd=true;
4527
4528 //check all tiles before this one
4529 for(int32_t checktile=((OnlyCheckNewTilesForDuplicates!=0)?start:0); ((temp_canadd==true)&&(checktile<currtile)); checktile++)
4530 {
4531 for(int32_t flipping=0; ((temp_canadd==true)&&(flipping<4)); ++flipping)
4532 {
4533 if(DuplicateAction[flipping]>0)
4534 {
4535 if(keypressed())
4536 {
4537 delete[] testtile;
4538 return true;
4539 }
4540
4541 duplicate=(newformat==imported_format);
4542
4543 if(duplicate)
4544 {
4545 switch(flipping)
4546 {
4547 case 0: //normal
4548 if(dest[checktile].data!=NULL)
4549 {
4550 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4551 {
4552 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4553 {
4554 // if ((dest[(checktile*128)+(y*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4555 if((dest[checktile].data[(y*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4556 {
4557 duplicate=false;
4558 }
4559 }
4560 }
4561 }
4562
4563 break;
4564
4565 case 1: //horizontal
4566 if(dest[checktile].data!=NULL)
4567 {
4568 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4569 {
4570 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4571 {
4572 // if ((dest[(checktile*128)+(y*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4573 if((dest[checktile].data[(y*8*newformat)+(14+(newformat-1)-x)/(3-newformat)])!=testtile[(y*16)+x])
4574 {
4575 duplicate=false;
4576 }
4577 }
4578 }
4579 }
4580
4581 break;
4582
4583 case 2: //vertical
4584 if(dest[checktile].data!=NULL)
4585 {
4586 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4587 {
4588 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4589 {
4590 // if ((dest[(checktile*128)+((15-y)*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4591 if((dest[checktile].data[((15-y)*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4592 {
4593 duplicate=false;
4594 }
4595 }
4596 }
4597 }
4598
4599 break;
4600
4601 case 3: //both
4602 if(dest[checktile].data!=NULL)
4603 {
4604 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4605 {
4606 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4607 {
4608 // if ((dest[(checktile*128)+((15-y)*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4609 if((dest[checktile].data[((15-y)*8*newformat)+((14+(newformat-1)-x)/(3-newformat))])!=testtile[(y*16)+x])
4610 {
4611 duplicate=false;
4612 }
4613 }
4614 }
4615 }
4616
4617 break;
4618 }
4619 }
4620
4621 if(duplicate==true)
4622 {
4623 ++duplicates_found[flipping];
4624 ++total_duplicates_found;
4625
4626 if(DuplicateAction[flipping]>1)
4627 {
4628 ++total_duplicates_discarded;
4629 temp_canadd=false;
4630 }
4631 }
4632 }
4633
4634 canadd=canadd&&temp_canadd;
4635 }
4636 }
4637 }
4638
4639 // dest[currtile].format=(cdepth==3?imported_format:cdepth);
4640 dest[currtile].format=newformat;
4641
4642 if(dest[currtile].data!=NULL)
4643 {
4644 free(dest[currtile].data);
4645 }
4646
4647 dest[currtile].data=(byte *)malloc(tilesize(dest[currtile].format));
4648
4649 if(dest[currtile].data==NULL)
4650 {
4651 Z_error_fatal("Unable to initialize tile #%d.\n", currtile);
4652 }
4653
4654 if(canadd==true)
4655 {
4656 /*
4657 for(int32_t y=0; y<16; y++)
4658 {
4659 for(int32_t x=0; x<8; x++)
4660 {
4661 dest[currtile].data[(y*8)+x]=testtile[(y*8)+x];
4662 }
4663 }
4664 */
4665 memcpy(dest[currtile].data, testtile, tilesize(dest[currtile].format));
4666 ++currtile;
4667 }
4668 }
4669 }
4670
4671 destroy_bitmap(status);
4672 delete[] testtile;
4673 return true;
4674 }
4675
4676 void grab(byte(*dest)[256],byte *def, int32_t width, int32_t height, int32_t oformat, byte *newformat)
4677 {
4678 byte defFormat=(bp==8) ? tf8Bit : tf4Bit;
4679 byte format=defFormat;
4680 int32_t stile = ((imagey*TILES_PER_ROW)+imagex)+(((sely/16)*TILES_PER_ROW)+(selx/16));
4681
4682 switch(imagetype)
4683 {
4684 case ftZGP:
4685 case ftQST:
4686 case ftZQT:
4687 case ftQSU:
4688 case ftTIL:
4689 case ftBIN:
4690 case ftBMP:
4691 for(int32_t ty=0; ty<height; ty++)
4692 {
4693 for(int32_t tx=0; tx<width; tx++)
4694 {
4695 format=defFormat;
4696 switch(imagetype)
4697 {
4698 case ftZGP:
4699 case ftQST:
4700 case ftZQT:
4701 case ftQSU:
4702 case ftTIL:
4703 format=grabtilebuf[stile+((ty*TILES_PER_ROW)+tx)].format;
4704 break;
4705 }
4706
4707 bool ever_did_unmasked = false;
4708
4709 for(int32_t y=0; y<16; y++)
4710 {
4711 for(int32_t x=0; x<16; x+=2)
4712 {
4713 bool masked = (y<8 && x<8 && grabmask&1) || (y<8 && x>7 && grabmask&2) || (y>7 && x<8 && grabmask&4) || (y>7 && x>7 && grabmask&8);
4714 if (masked)
4715 {
4716 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x)]=def[(y*16)+(x)];
4717 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x+1)]=def[(y*16)+(x+1)];
4718 }
4719 else
4720 {
4721 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x]=getpixel(screen2,(tx*16)+x+selx,(ty*16)+y+sely);
4722 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1]=getpixel(screen2,(tx*16)+x+1+selx,(ty*16)+y+sely);
4723 ever_did_unmasked = true;
4724 }
4725 if (format == tf4Bit)
4726 {
4727 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x] &= 15;
4728 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1] &= 15;
4729 }
4730 }
4731 }
4732
4733 if (ever_did_unmasked)
4734 newformat[(ty*TILES_PER_ROW)+tx] = format;
4735 }
4736 }
4737
4738 break;
4739
4740 default:
4741 for(int32_t i=0; i<200; i++)
4742 {
4743 for(int32_t j=0; j<256; j++)
4744 {
4745 dest[i][j]=0;
4746 }
4747
4748 newformat[i] = tf4Bit;
4749 }
4750
4751 break;
4752 }
4753 }
4754
4755 static void scale_imagebuf_bitmap()
4756 {
4757 imagebuf_bitmap_scale = std::clamp(imagebuf_bitmap_scale, -10, 10);
4758
4759 float scale = IMAGEBUF_SCALE;
4760 int nw = original_imagebuf_bitmap->w * scale;
4761 int nh = original_imagebuf_bitmap->h * scale;
4762 if (nw <= 0 || nh <= 0)
4763 return;
4764
4765 BITMAP* scaled_bmp = create_bitmap_ex(8, nw, nh);
4766 if (!scaled_bmp)
4767 return;
4768
4769 stretch_blit(original_imagebuf_bitmap, scaled_bmp, 0, 0, original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, 0, 0, nw, nh);
4770 if (imagebuf != original_imagebuf_bitmap)
4771 destroy_bitmap((BITMAP*)imagebuf);
4772 imagebuf = scaled_bmp;
4773 }
4774
4775 //Grabber is not grabbing to tile pages beyond pg. 252 right now. -ZX 18th June, 2019
4776 void grab_tile(int32_t tile,int32_t &cs)
4777 {
4778 zq_allow_tile_draw_cache = true;
4779
4780 int window_w = 640+6+6, window_h = 480+25+6;
4781 int window_x=(zq_screen_w-window_w)/2;
4782 int window_y=(zq_screen_h-window_h)/2;
4783 popup_zqdialog_start(window_x,window_y,window_w,window_h,-1);
4784 int window_xofs = 0;
4785 int screen_xofs=6;
4786 int screen_yofs=25;
4787 int panel_yofs=0;
4788 int bwidth = 61*1.5;
4789 int bheight = 20*1.5;
4790 int button_x = 255*2;
4791 int grab_ok_button_y = 168*2 + 32;
4792 int leech_button_x = 117*2;
4793 int leech_button_y = 166*2 + 32;
4794 int grab_cancel_button_y = 192*2 + 32;
4795 int file_button_y = 216*2 + 32;
4796 int rec_button_x = 117*2;
4797 int rec_button_y = 192*2 + 32;
4798
4799 int screen_y1 = 24;
4800 int screen_y2 = screen_y1+320-1;
4801
4802 int crect_x = 184+190;
4803 int crect_y = 168*2 + 32;
4804 int crect_w = 8*2;
4805 int crect_h = 8*2;
4806
4807 int xrect_x = 640 + 12 - 21;
4808 int xrect_y = 5;
4809
4810 byte newtile[200][256];
4811 BITMAP *screen3=create_bitmap_ex(8, zq_screen_w, zq_screen_h);
4812 clear_bitmap(screen3);
4813 byte newformat[200];
4814
4815 memset(newtile, 0, 200*256);
4816 memset(newformat, 0, 200);
4817
4818 static EXT_LIST list[] =
4819 {
4820 { (char *)"All Files (*.*)", NULL },
4821 { (char *)"Bitmap Image (*.bmp)", (char *)"bmp" },
4822 { (char *)"GIF Image (*.gif)", (char *)"gif" },
4823 { (char *)"JPEG Image (*.jpg, *.jpeg)", (char *)"jpg,jpeg" },
4824 { (char *)"ZC Tile Export (*.til)", (char *)"til" },
4825 { (char *)"ZC Quest Template (*.zqt)", (char *)"zqt" },
4826 { (char *)"ZC Quest (*.qst)", (char *)"qst" },
4827 { (char *)"ZC Graphics Pack (*.zgp)", (char *)"zgp" },
4828 { (char *)"ZC Unencoded Quest (*.qsu)", (char *)"qsu" },
4829 { (char *)"NES ROM Image (*.nes)", (char *)"nes" },
4830 { (char *)"SNES ROM Image (*.smc)", (char *)"smc" },
4831 { (char *)"Gameboy ROM Image (*.gb)", (char *)"gb" },
4832 { (char *)"Gameboy Advance ROM Image (*.gba)", (char *)"gba" },
4833 { NULL, NULL }
4834 };
4835
4836
4837 memset(cset_reduce_table, 0, 256);
4838 memset(col_diff,0,3*128);
4839 bool bdown=false;
4840 int done=0;
4841 int pal=0;
4842 int f=0;
4843 int black=vc(0),white=vc(15);
4844 int selwidth=1, selheight=1;
4845 int selx2=0, sely2=0;
4846 bool xreversed=false, yreversed=false;
4847 bool doleech=false, dofile=false, dopal=false;
4848
4849 int jwin_pal2[jcMAX];
4850 memcpy(jwin_pal2, jwin_pal, sizeof(int)*jcMAX);
4851
4852
4853 if(imagebuf==NULL)
4854 load_imagebuf();
4855
4856 calc_cset_reduce_table(imagepal, cs);
4857 calc_cset_reduce_table_8bit(imagepal);
4858 draw_grab_window();
4859 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
4860 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
4861
4862 while(gui_mouse_b())
4863 {
4864 /* do nothing */
4865 rest(1);
4866 }
4867
4868 do
4869 {
4870 HANDLE_CLOSE_ZQDLG();
4871 if(exiting_program) break;
4872 rest(4);
4873 bool redraw=false;
4874
4875 if(keypressed())
4876 {
4877 redraw=true;
4878
4879 switch(readkey()>>8)
4880 {
4881 case KEY_F:
4882 dofile=true;
4883 break;
4884
4885 case KEY_L:
4886 doleech=true;
4887 break;
4888
4889 case KEY_P:
4890 if(imagetype==ftBMP)
4891 {
4892 dopal=true;
4893 recolor=rcNone;
4894 calc_cset_reduce_table(imagepal, cs);
4895 }
4896
4897 break;
4898
4899 case KEY_ESC:
4900 done=1;
4901 break;
4902
4903 case KEY_ENTER_PAD:
4904 case KEY_ENTER:
4905 done=2;
4906 break;
4907
4908 case KEY_DOWN:
4909 if(CHECK_CTRL_CMD) sely=zc_min(sely+1,144);
4910 else ++imagey;
4911
4912 break;
4913
4914 case KEY_UP:
4915 if(CHECK_CTRL_CMD) sely=zc_max(sely-1,0);
4916 else --imagey;
4917
4918 break;
4919
4920 case KEY_RIGHT:
4921 if(CHECK_CTRL_CMD) selx=zc_min(selx+1,304);
4922 else ++imagex;
4923
4924 break;
4925
4926 case KEY_LEFT:
4927 if(CHECK_CTRL_CMD) selx=zc_max(selx-1,0);
4928 else --imagex;
4929
4930 break;
4931
4932 case KEY_PGDN:
4933 imagey+=10;
4934 break;
4935
4936 case KEY_PGUP:
4937 imagey-=10;
4938 break;
4939
4940 case KEY_HOME:
4941 imagex=imagey=0;
4942 break;
4943
4944 case KEY_EQUALS:
4945 case KEY_PLUS_PAD:
4946 cs = (cs<13) ? cs+1:0;
4947 if(recolor==rc4Bit)
4948 calc_cset_reduce_table(imagepal, cs);
4949 break;
4950
4951 case KEY_MINUS:
4952 case KEY_MINUS_PAD:
4953 cs = (cs>0) ? cs-1:13;
4954 if(recolor==rc4Bit)
4955 calc_cset_reduce_table(imagepal, cs);
4956 break;
4957
4958 case KEY_S:
4959 if(grabmode==1) grabmode=8;
4960 else if(grabmode==8) grabmode=16;
4961 else grabmode=1;
4962
4963 break;
4964
4965 case KEY_COMMA:
4966 if (imagetype == ftBMP)
4967 {
4968 imagebuf_bitmap_scale--;
4969 if (imagebuf_bitmap_scale == 0)
4970 imagebuf_bitmap_scale = -2;
4971 scale_imagebuf_bitmap();
4972 }
4973 break;
4974 case KEY_STOP:
4975 if (imagetype == ftBMP)
4976 {
4977 imagebuf_bitmap_scale++;
4978 if (imagebuf_bitmap_scale == -1)
4979 imagebuf_bitmap_scale = 1;
4980 scale_imagebuf_bitmap();
4981 }
4982 break;
4983
4984 case KEY_1:
4985 if(recolor==rc8Bit)
4986 recolor=rcNone;
4987 //imagex=(imagex*bp)>>3;
4988 bp=1;
4989 //imagex<<=3;
4990 nesmode=false;
4991 break;
4992
4993 case KEY_2:
4994 if(recolor==rc8Bit)
4995 recolor=rcNone;
4996 //imagex=(imagex*bp)>>3;
4997 bp=2;
4998 //imagex<<=2;
4999 nesmode=false;
5000 break;
5001
5002 case KEY_N:
5003 if(recolor==rc8Bit)
5004 recolor=rcNone;
5005 //imagex=(imagex*bp)>>3;
5006 bp=2;
5007 //imagex<<=2;
5008 nesmode=true;
5009 break;
5010
5011 case KEY_4:
5012 if(recolor==rc8Bit)
5013 recolor=rcNone;
5014 //imagex=(imagex*bp)>>3;
5015 bp=4;
5016 //imagex<<=1;
5017 nesmode=false;
5018 break;
5019
5020 case KEY_8:
5021 //imagex=(imagex*bp)>>3;
5022 bp=8;
5023 break;
5024
5025 case KEY_B:
5026 if(bp==2&&!nesmode)
5027 {
5028 nesmode=true;
5029 }
5030 else
5031 {
5032 nesmode=false;
5033 bp<<=1;
5034
5035 if(bp==16)
5036 {
5037 bp=1;
5038 //imagex<<=3;
5039 }
5040 else
5041 {
5042 //imagex>>=1;
5043 }
5044 }
5045
5046 break;
5047
5048 case KEY_M:
5049 romtilemode=(romtilemode+1)%4;
5050 break;
5051
5052 case KEY_Z:
5053 if(romofs>0) --romofs;
5054
5055 break;
5056
5057 case KEY_X:
5058 ++romofs;
5059 break;
5060
5061 case KEY_R:
5062 if(pal)
5063 {
5064 dopal=true;
5065 }
5066
5067 if(recolor!=rcNone)
5068 recolor=rcNone;
5069 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5070 {
5071 bp=8;
5072 recolor=rc8Bit;
5073 calc_cset_reduce_table_8bit(imagepal);
5074 }
5075 else
5076 {
5077 if(bp==8)
5078 bp=4;
5079 recolor=rc4Bit;
5080 calc_cset_reduce_table(imagepal, cs);
5081 }
5082 break;
5083
5084 default:
5085 redraw=false;
5086 }
5087
5088 clear_keybuf();
5089
5090 if(imagex<0) imagex=0;
5091
5092 if(imagey<0) imagey=0;
5093
5094 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5095 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5096 }
5097
5098 //boogie!
5099 if(gui_mouse_b()==1 && !bdown)
5100 {
5101 int x=gui_mouse_x();
5102 int y=gui_mouse_y();
5103 if(isinRect(x,y,xrect_x, xrect_y, xrect_x + 15, xrect_y + 13))
5104 if(do_x_button(screen, xrect_x, xrect_y))
5105 done=1;
5106
5107 if(!bdown)
5108 {
5109 bool regrab=false;
5110 bdown=true;
5111 FONT* oldfont = font;
5112 font = get_zc_font(font_lfont_l);
5113
5114 if(y>=screen_y1 && y<=screen_y2)
5115 {
5116 do
5117 {
5118 HANDLE_CLOSE_ZQDLG();
5119 if(exiting_program) break;
5120 int x = (gui_mouse_x()-screen_xofs) / 2;
5121 int y = (gui_mouse_y()-screen_yofs) / 2;
5122
5123 int ox=selx,oy=sely,ow=selwidth,oh=selheight;
5124
5125 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
5126 {
5127 selx=vbound((x/grabmode)*grabmode,0,304);
5128 sely=vbound((y/grabmode)*grabmode,0,144);
5129 selx2=selx;
5130 sely2=sely;
5131 selwidth=1;
5132 selheight=1;
5133 xreversed=false;
5134 yreversed=false;
5135 }
5136 else
5137 {
5138 if(xreversed)
5139 {
5140 zc_swap(selx, selx2);
5141 xreversed=false;
5142 }
5143
5144 if(yreversed)
5145 {
5146 zc_swap(sely, sely2);
5147 yreversed=false;
5148 }
5149
5150 selx2=vbound((x/grabmode)*grabmode,0,304);
5151 sely2=vbound((y/grabmode)*grabmode,0,144);
5152 selwidth=1+(abs(selx2-selx))/16;
5153 selheight=1+(abs(sely2-sely))/16;
5154
5155 if(selx2<selx)
5156 {
5157 zc_swap(selx, selx2);
5158 xreversed=true;
5159 }
5160
5161 if(sely2<sely)
5162 {
5163 zc_swap(sely, sely2);
5164 yreversed=true;
5165 }
5166 }
5167
5168 bool changed = (ox!=selx || oy!=sely || ow!=selwidth || oh!=selheight);
5169 bool redraw = changed || !(f%8);
5170
5171 if(redraw)
5172 {
5173 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5174 if(changed)
5175 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5176 if(f&8)
5177 {
5178 static const int w = 32;
5179 rect(screen,(selx*2)+screen_xofs,(sely*2)+screen_yofs,(selx*2)+screen_xofs+((selwidth-1)*w)+(w-1),(sely*2)+screen_yofs+((selheight-1)*w)+(w-1),white);
5180 }
5181 }
5182 else custom_vsync();
5183
5184 ++f;
5185 }
5186 while(gui_mouse_b());
5187 }
5188 else if(isinRect(x,y,button_x,grab_ok_button_y,button_x+bwidth,grab_ok_button_y+bheight))
5189 {
5190 if(do_text_button(button_x,grab_ok_button_y,bwidth,bheight,"OK"))
5191 done=2;
5192 }
5193 else if(isinRect(x,y,leech_button_x,leech_button_y,leech_button_x+bwidth,leech_button_y+bheight))
5194 {
5195 if(do_text_button(leech_button_x,leech_button_y,bwidth,bheight,"Leech"))
5196 {
5197 doleech=true;
5198 }
5199 }
5200 else if(isinRect(x,y,button_x,grab_cancel_button_y,button_x+bwidth,grab_cancel_button_y+bheight))
5201 {
5202 if(do_text_button(button_x,grab_cancel_button_y,bwidth,bheight,"Cancel"))
5203 done=1;
5204 }
5205 else if(isinRect(x,y,button_x,file_button_y,button_x+bwidth,file_button_y+bheight))
5206 {
5207 if(do_text_button(button_x,file_button_y,bwidth,bheight,"File"))
5208 {
5209 dofile=true;
5210 }
5211 }
5212 else if(imagetype == ftBMP && isinRect(x,y,rec_button_x, rec_button_y, rec_button_x+bwidth, rec_button_y+bheight))
5213 {
5214 if(do_text_button(rec_button_x,rec_button_y,bwidth,bheight,"Recolor"))
5215 {
5216 if(pal)
5217 {
5218 dopal = true;
5219 }
5220
5221 if(recolor!=rcNone)
5222 recolor=rcNone;
5223 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5224 {
5225 bp=8;
5226 recolor=rc8Bit;
5227 calc_cset_reduce_table_8bit(imagepal);
5228 }
5229 else
5230 {
5231 if(bp==8)
5232 bp=4;
5233 recolor=rc4Bit;
5234 calc_cset_reduce_table(imagepal, cs);
5235 }
5236 redraw=true;
5237 }
5238 }
5239 else if(isinRect(x,y+panel_yofs,crect_x,crect_y,crect_x+(16),crect_y+crect_h-1))
5240 {
5241 regrab=true;
5242 grabmask^=1;
5243 }
5244 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y,crect_x+(32)-1,crect_y+crect_h-1))
5245 {
5246 regrab=true;
5247 grabmask^=2;
5248 }
5249 else if(isinRect(x,y+panel_yofs,crect_x,crect_y+crect_h,crect_x+(16)-1,crect_y+crect_h+crect_h-1))
5250 {
5251 regrab=true;
5252 grabmask^=4;
5253 }
5254 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y+crect_h,crect_x+(32)-1,crect_y+crect_h+crect_h-1))
5255 {
5256 regrab=true;
5257 grabmask^=8;
5258 }
5259
5260 if(regrab)
5261 {
5262 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5263 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5264 redraw=true;
5265 }
5266
5267 font = oldfont;
5268 }
5269 }
5270
5271 if(gui_mouse_b()==0)
5272 bdown=false;
5273
5274 if(dofile)
5275 {
5276
5277 if(getname_nogo("Load File",NULL,list,imagepath,true))
5278 {
5279 zc_set_palette(RAMpal);
5280 pal=0;
5281 white=vc(15);
5282 black=vc(0);
5283 strcpy(imagepath,temppath);
5284 load_imagebuf();
5285 imagex=imagey=0;
5286 calc_cset_reduce_table(imagepal, cs);
5287 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5288 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5289 }
5290
5291 while(key[KEY_ESC])
5292 {
5293 poll_keyboard();
5294 /* do nothing */
5295 rest(1);
5296 }
5297
5298 clear_keybuf();
5299 dofile=false;
5300 redraw=true;
5301 }
5302
5303 if(doleech)
5304 {
5305 if(leech_tiles(newtilebuf,tile,cs))
5306 {
5307 done=1;
5308 }
5309 else
5310 {
5311 while(key[KEY_ESC])
5312 {
5313 poll_keyboard();
5314 /* do nothing */
5315 rest(1);
5316 }
5317
5318 clear_keybuf();
5319 redraw=true;
5320 }
5321
5322 doleech=false;
5323 }
5324
5325 if(dopal)
5326 {
5327 pal^=1;
5328
5329 if(pal)
5330 {
5331 get_bw(imagepal,black,white);
5332
5333 jwin_pal[jcBOX] =imagepal_table.data[0][jwin_pal[jcBOX]];
5334 jwin_pal[jcLIGHT] =imagepal_table.data[0][jwin_pal[jcLIGHT]];
5335 jwin_pal[jcMEDLT] =imagepal_table.data[0][jwin_pal[jcMEDLT]];
5336 jwin_pal[jcMEDDARK]=imagepal_table.data[0][jwin_pal[jcMEDDARK]];
5337 jwin_pal[jcDARK] =imagepal_table.data[0][jwin_pal[jcDARK]];
5338 jwin_pal[jcBOXFG] =imagepal_table.data[0][jwin_pal[jcBOXFG]];
5339 jwin_pal[jcTITLEL] =imagepal_table.data[0][jwin_pal[jcTITLEL]];
5340 jwin_pal[jcTITLER] =imagepal_table.data[0][jwin_pal[jcTITLER]];
5341 jwin_pal[jcTITLEFG]=imagepal_table.data[0][jwin_pal[jcTITLEFG]];
5342 jwin_pal[jcTEXTBG] =imagepal_table.data[0][jwin_pal[jcTEXTBG]];
5343 jwin_pal[jcTEXTFG] =imagepal_table.data[0][jwin_pal[jcTEXTFG]];
5344 jwin_pal[jcSELBG] =imagepal_table.data[0][jwin_pal[jcSELBG]];
5345 jwin_pal[jcSELFG] =imagepal_table.data[0][jwin_pal[jcSELFG]];
5346 gui_bg_color=jwin_pal[jcBOX];
5347 gui_fg_color=jwin_pal[jcBOXFG];
5348 jwin_set_colors(jwin_pal);
5349 }
5350 else
5351 {
5352 white=vc(15);
5353 black=vc(0);
5354
5355 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5356 gui_bg_color=jwin_pal[jcBOX];
5357 gui_fg_color=jwin_pal[jcBOXFG];
5358 jwin_set_colors(jwin_pal);
5359 }
5360
5361 zc_set_palette_range(pal?imagepal:RAMpal,0,255,false);
5362
5363 dopal=false;
5364 redraw=true;
5365 }
5366
5367 if(redraw)
5368 {
5369 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5370 }
5371 else
5372 {
5373 custom_vsync();
5374 }
5375
5376 if((f%8)==0)
5377 {
5378 stretch_blit(screen2,screen3,0, 0, zq_screen_w, zq_screen_h, 0, 0, zq_screen_w*2, zq_screen_h*2);
5379
5380 int selxl = selx* 2;
5381 int selyl = sely* 2;
5382 int w = 32;
5383
5384 if(f&8)
5385 rect(screen3,selxl,selyl,selxl+((selwidth-1)*w)+(w-1),selyl+((selheight-1)*w)+(w-1),white);
5386
5387 blit(screen3,screen,selxl,selyl,selxl+screen_xofs,selyl+screen_yofs,selwidth*w,selheight*w);
5388 }
5389
5390 // SCRFIX();
5391 ++f;
5392
5393 }
5394 while(!done);
5395
5396 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5397 gui_bg_color=jwin_pal[jcBOX];
5398 gui_fg_color=jwin_pal[jcBOXFG];
5399 jwin_set_colors(jwin_pal);
5400
5401
5402 if(done==2)
5403 {
5404 go_tiles();
5405 saved=false;
5406
5407 // usetiles=true;
5408 for(int y=0; y<selheight; y++)
5409 {
5410 for(int x=0; x<selwidth; x++)
5411 {
5412 int temptile=tile+((TILES_PER_ROW*y)+x);
5413 int format=(bp==8) ? tf8Bit : tf4Bit;
5414
5415 if(newtilebuf[temptile].data!=NULL)
5416 free(newtilebuf[temptile].data);
5417
5418 newtilebuf[temptile].format=format;
5419 newtilebuf[temptile].data=(byte *)malloc(tilesize(format));
5420
5421 if(newtilebuf[temptile].data==NULL)
5422 {
5423 Z_error_fatal("Unable to initialize tile #%d.\n", temptile);
5424 break;
5425 }
5426
5427 for(int i=0; i<256; i++)
5428 {
5429 // newtilebuf[temptile].data[i] = cset_reduce_table[newtile[(TILES_PER_ROW*y)+x][i]];
5430 newtilebuf[temptile].data[i] = newtile[(TILES_PER_ROW*y)+x][i];
5431 }
5432
5433 // unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
5434 }
5435 }
5436 }
5437
5438 destroy_bitmap(screen3);
5439
5440 if(pal)
5441 zc_set_palette(RAMpal);
5442
5443 recolor=rcNone;
5444 calc_cset_reduce_table(imagepal, cs);
5445 register_blank_tiles();
5446 popup_zqdialog_end();
5447
5448 zq_allow_tile_draw_cache = false;
5449 }
5450
5451 int32_t show_only_unused_tiles=4; //1 bit: hide used, 2 bit: hide unused, 4 bit: hide blank
5452 bool tile_is_used(int32_t tile)
5453 {
5454 return used_tile_table[tile];
5455 }
5456 void draw_tiles(int32_t first,int32_t cs, int32_t f)
5457 {
5458 draw_tiles(screen2, first, cs, f, true);
5459 }
5460 void draw_tiles(BITMAP* dest,int32_t first,int32_t cs, int32_t f, bool large, bool true_empty)
5461 {
5462 clear_bitmap(dest);
5463 BITMAP *buf = create_bitmap_ex(8,16,16);
5464
5465 int32_t w = 16;
5466 int32_t h = 16;
5467
5468 if(large)
5469 {
5470 w *=2;
5471 h *=2;
5472 }
5473
5474 for(int32_t i=0; i<TILES_PER_PAGE; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
5475 {
5476 int32_t x = (i%TILES_PER_ROW)<<4;
5477 int32_t y = (i/TILES_PER_ROW)<<4;
5478 int32_t l = 16;
5479
5480 if(large)
5481 {
5482 x*=2;
5483 y*=2;
5484 l*=2;
5485 }
5486
5487 l-=2;
5488
5489 if((HIDE_USED && tile_is_used(first+i) && !blank_tile_table[first+i]) // 1 bit: hide used
5490 || (HIDE_UNUSED && !tile_is_used(first+i) && !blank_tile_table[first+i]) // 2 bit: hide unused
5491 || (HIDE_BLANK && blank_tile_table[first+i])) // 4 bit: hide blank
5492 {
5493 if(!true_empty) //Use pure color 0; no effects
5494 {
5495 if (InvalidBG == 2)
5496 {
5497 draw_checkerboard(dest, x, y, w);
5498 }
5499 else if(InvalidBG == 1)
5500 {
5501 for(int32_t dy=0; dy<=l+1; dy++)
5502 {
5503 for(int32_t dx=0; dx<=l+1; dx++)
5504 {
5505 dest->line[dy+(y)][dx+(x)]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5506 }
5507 }
5508 }
5509 else
5510 {
5511 for(int32_t dy=0; dy<=l+1; dy++)
5512 {
5513 for(int32_t dx=0; dx<=l+1; dx++)
5514 {
5515 dest->line[dy+(y)][dx+(x)]=vc(0);
5516 }
5517 }
5518 rect(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5519 line(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5520 line(dest, (x)+1,(y)+l, (x)+l, (y)+1, vc(15));
5521 }
5522 }
5523 }
5524 else
5525 {
5526 puttile16(buf,first+i,0,0,cs,0);
5527 stretch_blit(buf,dest,0,0,16,16,x,y,w,h);
5528 }
5529
5530 if((f%32)<=16 && large && !HIDE_8BIT_MARKER && newtilebuf[first+i].format==tf8Bit)
5531 {
5532 textprintf_ex(dest,get_zc_font(font_z3smallfont),(x)+l-3,(y)+l-3,vc(int32_t((f%32)/6)+10),-1,"8");
5533 }
5534 }
5535
5536 destroy_bitmap(buf);
5537 }
5538
5539 void tile_info_0(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,bool rect_sel)
5540 {
5541 int32_t yofs=3;
5542 BITMAP *buf = create_bitmap_ex(8,16,16);
5543 int32_t mul = 2;
5544 FONT *tfont = get_zc_font(font_pfont);
5545
5546 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5547 _allegro_hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5548 _allegro_hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5549 tfont = get_zc_font(font_lfont_l);
5550
5551 // Copied tile and numbers
5552 jwin_draw_frame(screen2,(34*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5553 int32_t coldiff=TILECOL(copy)-TILECOL(copy+copycnt-1);
5554 if(copy>=0)
5555 {
5556 puttile16(buf,rect_sel&&coldiff>0?copy-coldiff:copy,0,0,cs,0);
5557 stretch_blit(buf,screen2,0,0,16,16,34*mul,216*mul+yofs,16*mul,16*mul);
5558
5559 if(copycnt>1)
5560 {
5561 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
5562 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
5563 }
5564 else
5565 {
5566 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
5567 }
5568 }
5569 else // No tiles copied
5570 {
5571 if (InvalidBG == 2)
5572 {
5573 draw_checkerboard(screen2, 34 * mul, 216 * mul + yofs, 16 * mul);
5574 }
5575 else if(InvalidBG == 1)
5576 {
5577 for(int32_t dy=0; dy<16*mul; dy++)
5578 {
5579 for(int32_t dx=0; dx<16*mul; dx++)
5580 {
5581 screen2->line[(216*mul+yofs+dy)][36*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5582 }
5583 }
5584 }
5585 else
5586 {
5587 rectfill(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(0));
5588 rect(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5589 line(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5590 line(screen2, 34*mul, ((216+15)*mul)+yofs, (34+15)*mul, (216*mul)+yofs, vc(15));
5591 }
5592 }
5593
5594
5595 // Current tile
5596 jwin_draw_frame(screen2,(104*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5597 puttile16(buf,tile,0,0,cs,0);
5598 stretch_blit(buf,screen2,0,0,16,16,104*mul,216*mul+yofs,16*mul,16*mul);
5599
5600 // Current selection mode
5601 jwin_draw_frame(screen2,(127*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5602 stretch_blit(select_bmp[rect_sel?1:0],screen2,0,0,16,16,127*mul,216*mul+yofs,16*mul,16*mul);
5603
5604 if(tile>tile2)
5605 {
5606 zc_swap(tile,tile2);
5607 }
5608
5609 char tbuf[8];
5610 tbuf[0]=0;
5611
5612 if(tile2!=tile)
5613 {
5614 sprintf(tbuf,"-%d",tile2);
5615 }
5616
5617 // Current tile and CSet text
5618 textprintf_ex(screen2,tfont,55*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cs: %d",cs);
5619 textprintf_right_ex(screen2,tfont,99*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile:");
5620 textprintf_right_ex(screen2,tfont,99*mul,224*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,tbuf);
5621
5622 FONT *tf = font;
5623 font = tfont;
5624
5625 draw_text_button(screen2,150*mul,213*mul+yofs,28*mul,21*mul,"&Grab",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5626 draw_text_button(screen2,(150+28)*mul,213*mul+yofs,28*mul,21*mul,"&Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5627 draw_text_button(screen2,(150+28*2)*mul,213*mul+yofs,28*mul,21*mul,"Export",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5628 draw_text_button(screen2,(150+28*3)*mul,213*mul+yofs,28*mul,21*mul,"Recolor",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5629 draw_text_button(screen2,(150+28*4)*mul,213*mul+yofs,28*mul,21*mul,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5630
5631 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5632 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5633 textprintf_centre_ex(screen2,tfont,(305*mul+4),220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5634 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5635
5636 font = tf;
5637
5638 int32_t w = 640;
5639 int32_t h = 480;
5640 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5641 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5642 int32_t screen_xofs=window_xofs+6;
5643 int32_t screen_yofs=window_yofs+25;
5644
5645 custom_vsync();
5646 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5647 SCRFIX();
5648 destroy_bitmap(buf);
5649 }
5650
5651 void tile_info_1(int32_t oldtile,int32_t oldflip,int32_t oldcs,int32_t tile,int32_t flip,int32_t cs,int32_t copy,int32_t page, bool always_use_flip)
5652 {
5653 int32_t yofs=3;
5654 BITMAP *buf = create_bitmap_ex(8,16,16);
5655 int32_t mul = 2;
5656 FONT *tfont = get_zc_font(font_pfont);
5657
5658 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5659 _allegro_hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5660 _allegro_hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5661 tfont = get_zc_font(font_lfont_l);
5662
5663 jwin_draw_frame(screen2,(124*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5664
5665 if(copy>=0)
5666 {
5667 puttile16(buf,copy,0,0,cs,flip);
5668 stretch_blit(buf,screen2,0,0,16,16,124*mul,216*mul+yofs,16*mul,16*mul);
5669 }
5670 else
5671 {
5672 if (InvalidBG == 2)
5673 {
5674 draw_checkerboard(screen2, 124 * mul, 216 * mul + yofs, 16 * mul);
5675 }
5676 else if(InvalidBG == 1)
5677 {
5678 for(int32_t dy=0; dy<16*mul; dy++)
5679 {
5680 for(int32_t dx=0; dx<16*mul; dx++)
5681 {
5682 screen2->line[216*mul+yofs+dy][124*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5683 }
5684 }
5685 }
5686 else
5687 {
5688 rectfill(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(0));
5689 rect(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5690 line(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5691 line(screen2, 124*mul, ((216+15)*mul)+yofs, (124+15)*mul, (216*mul)+yofs, vc(15));
5692 }
5693 }
5694
5695 jwin_draw_frame(screen2,(8*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5696 puttile16(buf,oldtile,0,0, oldcs, oldflip);
5697 stretch_blit(buf,screen2,0,0,16,16,8*mul,216*mul+yofs,16*mul,16*mul);
5698
5699 textprintf_right_ex(screen2,tfont,56*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Old Tile:");
5700 textprintf_ex(screen2,tfont,60*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldtile);
5701
5702 textprintf_right_ex(screen2,tfont,56*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5703 textprintf_ex(screen2,tfont,60*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldcs);
5704
5705 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5706 {
5707 textprintf_right_ex(screen2,tfont,56*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5708 textprintf_ex(screen2,tfont,60*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldflip);
5709 }
5710
5711 jwin_draw_frame(screen2,(148*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5712 puttile16(buf,tile,0,0, cs,
5713 (oldflip>0 || always_use_flip)?flip:0); // Suppress Flip for this usage
5714 stretch_blit(buf,screen2,0,0,16,16,148*mul,216*mul+yofs,16*mul,16*mul);
5715
5716 textprintf_right_ex(screen2,tfont,201*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"New Tile:");
5717 textprintf_ex(screen2,tfont,205*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",tile);
5718 textprintf_right_ex(screen2,tfont,201*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5719 textprintf_ex(screen2,tfont,205*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",cs);
5720
5721 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5722 {
5723 textprintf_right_ex(screen2,tfont,201*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5724 textprintf_ex(screen2,tfont,205*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",flip);
5725 }
5726
5727 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5728 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5729 textprintf_centre_ex(screen2,tfont,309*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5730 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5731
5732
5733 int32_t w = 640;
5734 int32_t h = 480;
5735 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5736 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5737 int32_t screen_xofs=window_xofs+6;
5738 int32_t screen_yofs=window_yofs+25;
5739
5740 custom_vsync();
5741 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5742 SCRFIX();
5743 destroy_bitmap(buf);
5744 }
5745 /*
5746 void reset_tile(tiledata *buf, int32_t t, int32_t format=1)
5747 {
5748 buf[t].format=format;
5749 if (buf[t].data!=NULL)
5750 {
5751 free(buf[t].data);
5752 }
5753 buf[t].data=(byte *)malloc(tilesize(buf[t].format));
5754 if (buf[t].data==NULL)
5755 {
5756 Z_error_fatal("Unable to initialize tile #%d.\n", t);
5757 }
5758 for(int32_t i=0; i<tilesize(buf[t].format); i++)
5759 {
5760 buf[t].data[i]=0;
5761 }
5762 }
5763 */
5764
5765 int32_t hide_used()
5766 {
5767 show_only_unused_tiles ^= 1;
5768 return D_O_K;
5769 }
5770 int32_t hide_unused()
5771 {
5772 show_only_unused_tiles ^= 2;
5773 return D_O_K;
5774 }
5775 int32_t hide_blank()
5776 {
5777 show_only_unused_tiles ^= 4;
5778 return D_O_K;
5779 }
5780 int32_t hide_8bit_marker()
5781 {
5782 show_only_unused_tiles ^= 8;
5783 return D_O_K;
5784 }
5785
5786 enum
5787 {
5788 MENUID_SELTILE_VIEW_HIDE_USED,
5789 MENUID_SELTILE_VIEW_HIDE_UNUSED,
5790 MENUID_SELTILE_VIEW_HIDE_BLANK,
5791 MENUID_SELTILE_VIEW_HIDE_8BIT,
5792 };
5793
1/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
9 static NewMenu select_tile_view_menu
5794 45 {
5795
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide Used", hide_used, MENUID_SELTILE_VIEW_HIDE_USED },
5796
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide Unused", hide_unused, MENUID_SELTILE_VIEW_HIDE_UNUSED },
5797
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide Blank", hide_blank, MENUID_SELTILE_VIEW_HIDE_BLANK },
5798
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide 8-bit marker", hide_8bit_marker, MENUID_SELTILE_VIEW_HIDE_8BIT },
5799 };
5800
5801 //returns the row the tile is in on its page
5802 int32_t tile_page_row(int32_t tile)
5803 {
5804 return TILEROW(tile)-(TILEPAGE(tile)*TILE_ROWS_PER_PAGE);
5805 }
5806
5807 enum {ti_none, ti_encompass, ti_broken};
5808
5809 //striped check and striped selection
5810 int32_t move_intersection_ss(newcombo &cmb, int32_t selection_first, int32_t selection_last, int32_t offset = 0)
5811 {
5812 int32_t cmb_first = cmb.o_tile;
5813 int32_t cmb_last = cmb.o_tile;
5814 do
5815 {
5816 cmb_last = cmb.tile;
5817 animate(cmb, true);
5818 }
5819 while(cmb.tile != cmb.o_tile);
5820 reset_combo_animation(cmb);
5821 cmb_first += offset;
5822 cmb_last += offset;
5823
5824 if(cmb_first > selection_last || cmb_last < selection_first)
5825 return ti_none;
5826 if(cmb_first >= selection_first && cmb_last <= selection_last)
5827 return ti_encompass;
5828
5829 do
5830 {
5831 if(cmb.tile+offset >= selection_first && cmb.tile+offset <= selection_last)
5832 {
5833 reset_combo_animation(cmb);
5834 return ti_broken; //contained, but non-encompassing.
5835 }
5836 animate(cmb, true);
5837 }
5838 while(cmb.tile != cmb.o_tile);
5839 reset_combo_animation(cmb);
5840 return ti_none;
5841 }
5842 int32_t move_intersection_ss(int32_t check_first, int32_t check_last, int32_t selection_first, int32_t selection_last)
5843 {
5844 // if selection is before or after check...
5845 if((check_first>selection_last)||(selection_first>check_last))
5846 {
5847 return ti_none;
5848 }
5849
5850 // if selection envelopes check
5851 if((selection_first<=check_first)&&(selection_last>=check_last))
5852 {
5853 return ti_encompass; //encompass
5854 }
5855
5856 //everything else is a break
5857 return ti_broken; //intersect
5858 }
5859
5860
5861
5862 //rectangular check and striped selection
5863 int32_t move_intersection_rs(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_first, int32_t selection_last)
5864 {
5865 int32_t ret1=-1, ret2=-1;
5866
5867 for(int32_t i=0; i<check_height; ++i)
5868 {
5869 int32_t check_first=((check_top+i)*TILES_PER_ROW)+check_left;
5870 int32_t check_last=check_first+check_width-1;
5871 ret2=move_intersection_ss(check_first, check_last, selection_first, selection_last);
5872
5873 if(ret2==ti_broken)
5874 {
5875 return ti_broken;
5876 }
5877
5878 ret1=(ret2==ti_encompass?ti_encompass:ret1);
5879 }
5880
5881 if(ret1==ti_encompass)
5882 {
5883 if((TILEROW(selection_first)<=check_top) &&
5884 (TILEROW(selection_last)>=(check_top+check_height-1)))
5885 {
5886 return ti_encompass;
5887 }
5888 else
5889 {
5890 return ti_broken;
5891 }
5892 }
5893
5894 return ti_none;
5895 }
5896
5897
5898 //striped check and rectangular selection
5899 int32_t move_intersection_sr(newcombo &cmb, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height, int32_t offset = 0)
5900 {
5901 if(selection_width < TILES_PER_ROW)
5902 {
5903 int32_t cmb_first = cmb.o_tile;
5904 int32_t cmb_last = cmb.o_tile;
5905 do
5906 {
5907 cmb_last = cmb.tile;
5908 animate(cmb, true);
5909 }
5910 while(cmb.tile != cmb.o_tile);
5911 reset_combo_animation(cmb);
5912 cmb_first += offset;
5913 cmb_last += offset;
5914
5915 if((TILEROW(cmb_first)>=selection_top) &&
5916 (TILEROW(cmb_last)<=selection_top+selection_height-1) &&
5917 (TILECOL(cmb_first)>=selection_left) &&
5918 (TILECOL(cmb_last)<=TILECOL(selection_left+selection_width-1)))
5919 {
5920 return ti_encompass;
5921 }
5922 else if((cmb_last<selection_top*TILES_PER_ROW+selection_left) ||
5923 (cmb_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
5924 {
5925 return ti_none;
5926 }
5927
5928 if(TILEROW(cmb_first) == TILEROW(cmb_last))
5929 {
5930 int32_t firstcol = TILECOL(cmb_first);
5931 int32_t lastcol = TILECOL(cmb_last);
5932
5933 if(lastcol < selection_left || firstcol >= selection_left+selection_width)
5934 return ti_none;
5935 else //handle skip x
5936 {
5937 do
5938 {
5939 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width)
5940 {
5941 reset_combo_animation(cmb);
5942 return ti_broken;
5943 }
5944 animate(cmb, true);
5945 }
5946 while(cmb.tile != cmb.o_tile);
5947 reset_combo_animation(cmb);
5948 return ti_none;
5949 }
5950 }
5951 else //multi-row combo...
5952 {
5953 int32_t row = TILEROW(cmb_first);
5954
5955 do
5956 {
5957 if(row < selection_top || row > selection_top+selection_height-1)
5958 {
5959 //This row isn't in the selection; skip to next row
5960 do
5961 {
5962 animate(cmb,true);
5963 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5964 }
5965 while(TILEROW(cmb.tile) == row);
5966 row = TILEROW(cmb.tile);
5967 continue;
5968 }
5969
5970 //This row IS in the selection; check each tile.
5971 do
5972 {
5973 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width-1)
5974 {
5975 reset_combo_animation(cmb);
5976 return ti_broken;
5977 }
5978 animate(cmb, true);
5979 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5980 }
5981 while(TILEROW(cmb.tile) == row);
5982 row = TILEROW(cmb.tile);
5983 }
5984 while(cmb.tile != cmb.o_tile);
5985
5986 return ti_none; //...Theoretically unreachable, but if it DOES get here, it's done.
5987 }
5988 }
5989
5990 return move_intersection_ss(cmb, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1, offset);
5991 }
5992 int32_t move_intersection_sr(int32_t check_first, int32_t check_last, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
5993 {
5994 if(selection_width < TILES_PER_ROW)
5995 {
5996 if((check_last-check_first+1<=selection_width) &&
5997 (TILEROW(check_first)>=selection_top) &&
5998 (TILEROW(check_last)<=selection_top+selection_height-1) &&
5999 (TILECOL(check_first)>=selection_left) &&
6000 (TILECOL(check_last)<=TILECOL(selection_left+selection_width-1)))
6001 {
6002 return ti_encompass;
6003 }
6004 else if((check_last<selection_top*TILES_PER_ROW+selection_left) ||
6005 (check_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
6006 {
6007 return ti_none;
6008 }
6009
6010 //else if (selection_top*TILES_PER_ROW+selection_left<check_first && (selection_top+1)*TILES_PER_ROW+selection_left>check_last)
6011
6012 //one last base case: the strip we're interested in only lies along one row
6013 if(check_first/TILES_PER_ROW == check_last/TILES_PER_ROW)
6014 {
6015 int32_t cfcol = check_first%TILES_PER_ROW;
6016 int32_t clcol = check_last%TILES_PER_ROW;
6017
6018 if(clcol < selection_left || cfcol >= selection_left+selection_width)
6019 return ti_none;
6020 else
6021 return ti_broken;
6022 }
6023 else
6024 {
6025 //recursively cut the strip into substrips which lie entirely on one row
6026 int32_t currow = check_first/TILES_PER_ROW;
6027 int32_t endrow = check_last/TILES_PER_ROW;
6028 int32_t accum = 0;
6029 accum |= move_intersection_sr(check_first,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6030
6031 for(++currow; currow<endrow; currow++)
6032 {
6033 accum |= move_intersection_sr(currow*TILES_PER_ROW,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6034 }
6035
6036 accum |= move_intersection_sr(currow*TILES_PER_ROW, check_last,selection_left,selection_top,selection_width,selection_height);
6037
6038 if(accum > 0)
6039 return ti_broken;
6040
6041 return ti_none;
6042 }
6043 }
6044
6045 return move_intersection_ss(check_first, check_last, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1);
6046 }
6047
6048 //rectangular check and rectangular selection
6049 int32_t move_intersection_rr(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6050 {
6051 if((check_left>=selection_left) &&
6052 (check_left+check_width<=selection_left+selection_width) &&
6053 (check_top>=selection_top) &&
6054 (check_top+check_height<=selection_top+selection_height))
6055 {
6056 return ti_encompass;
6057 }
6058 else
6059 {
6060 for(int32_t i=check_top; i<check_top+check_height; ++i)
6061 {
6062 if(move_intersection_rs(selection_left, selection_top, selection_width, selection_height, i*TILES_PER_ROW+check_left, i*TILES_PER_ROW+check_left+check_width-1)!=ti_none)
6063 {
6064 return ti_broken;
6065 }
6066 }
6067 }
6068
6069 return ti_none;
6070 }
6071
6072
6073
6074
6075 static DIALOG move_textbox_list_dlg[] =
6076 {
6077 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
6078 9 { jwin_win_proc, 0, 0, 300, 212, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6079 9 { jwin_ctext_proc, 150, 18, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6080 9 { jwin_ctext_proc, 150, 28, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6081 9 { jwin_textbox_proc, 12, 40, 277, 138, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6082 9 { jwin_button_proc, 80, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
6083 9 { jwin_button_proc, 160, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
6084 9 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
6085 9 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
6086 };
6087
6088 bool popup_move_textbox_dlg(string const& msg, char* textbox, char const* title)
6089 {
6090 char buf1[512] = {0};
6091 char buf2[512] = {0};
6092 large_dialog(move_textbox_list_dlg);
6093 DIALOG& tbox = move_textbox_list_dlg[3];
6094 {
6095 FONT* f = tbox.dp2 ? (FONT*)tbox.dp2 : get_custom_font(CFONT_GUI);
6096 int indx = 0, word_indx = 0;
6097 for(char c : msg)
6098 {
6099 if(c == ' ' || c == '\n')
6100 word_indx = indx;
6101 buf1[indx++] = c;
6102 if(c == '\n' || text_length(f, buf1) >= tbox.w)
6103 {
6104 buf1[word_indx] = 0;
6105 strcpy(buf2, msg.c_str()+word_indx+1);
6106 break;
6107 }
6108 }
6109 }
6110
6111 move_textbox_list_dlg[0].dp = (void*)title;
6112 move_textbox_list_dlg[0].dp2 = get_zc_font(font_lfont);
6113 move_textbox_list_dlg[1].dp = buf1;
6114 move_textbox_list_dlg[2].dp = buf2;
6115 tbox.dp = textbox;
6116 tbox.d2 = 0;
6117 auto tby = tbox.y;
6118 auto tbh = tbox.h;
6119 if(!buf2[0])
6120 {
6121 auto diff = move_textbox_list_dlg[2].h;
6122 tbox.y -= diff;
6123 tbox.h += diff;
6124 }
6125
6126 int32_t ret=do_zqdialog(move_textbox_list_dlg,2);
6127 position_mouse_z(0);
6128 tbox.y = tby;
6129 tbox.h = tbh;
6130
6131 return ret == 4;
6132 }
6133
6134 int32_t quick_select_3(int32_t a, int32_t b, int32_t c, int32_t d)
6135 {
6136 return a==0?b:a==1?c:d;
6137 }
6138
6139 bool TileMoveList::process(std::unique_ptr<BaseTileRef>& ref, TileMoveProcess const& proc, bool is_dest)
6140 {
6141 TileRefCombo* combo_ref = dynamic_cast<TileRefCombo*>(ref.get());
6142 int i = ti_none;
6143 auto t = ref->getTile() + ref->offset();
6144
6145 if(combo_ref)
6146 {
6147 if(proc.rect)
6148 i=move_intersection_sr(*combo_ref->combo, proc._l, proc._t, proc._w, proc._h);
6149 else i=move_intersection_ss(*combo_ref->combo, proc._first, proc._last);
6150 }
6151 else if(proc.rect)
6152 {
6153 if(ref->h > 1)
6154 i=move_intersection_rr(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._l, proc._t, proc._w, proc._h);
6155 else i=move_intersection_sr(t, t+ref->w-1, proc._l, proc._t, proc._w, proc._h);
6156 }
6157 else
6158 {
6159 if(ref->h > 1)
6160 i=move_intersection_rs(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._first, proc._last);
6161 else i=move_intersection_ss(t, t+ref->w-1, proc._first, proc._last);
6162 }
6163
6164 bool in = i != ti_none, out = i != ti_encompass;
6165 for(size_t q = 0; !(in&&out) && q < ref->extra_rects.size(); ++q)
6166 {
6167 auto [ex_t,ex_w,ex_h] = ref->extra_rects[q];
6168 if(proc.rect)
6169 i = move_intersection_rr(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._l, proc._t, proc._w, proc._h);
6170 else i = move_intersection_rs(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._first, proc._last);
6171 if(i != ti_none)
6172 in = true;
6173 if(i != ti_encompass)
6174 out = true;
6175 }
6176 i = in ? (out ? ti_broken : ti_encompass) : ti_none;
6177
6178 if(i != ti_none && ref->getTile() != 0)
6179 {
6180 if(mode == Mode::CHECK_ALL)
6181 {
6182 move_refs.emplace_back(std::move(ref));
6183 return true;
6184 }
6185 else if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6186 {
6187 if(warning_flood || warning_list.tellp() >= 65000)
6188 {
6189 if(!warning_flood)
6190 warning_list << "...\n...\n...\nmany others";
6191 warning_flood = true;
6192 }
6193 else
6194 warning_list << ref->name << '\n';
6195 }
6196 else if(i==ti_encompass)
6197 {
6198 move_refs.emplace_back(std::move(ref));
6199 return true;
6200 }
6201 }
6202 return false;
6203 }
6204
6205 bool TileMoveList::check_prot()
6206 {
6207 if(!TileProtection)
6208 return true;
6209 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Tile Warning");
6210
6211 warning_flood = false;
6212 warning_list.clear();
6213
6214 return ret;
6215 }
6216
6217 void TileMoveList::add_diff(int diff)
6218 {
6219 for(auto& ref : move_refs)
6220 ref->addTile(diff);
6221 }
6222
6223 //from 'combo.h'
6224 bool ComboMoveList::process(std::unique_ptr<BaseComboRef>& ref, ComboMoveProcess const& proc, bool is_dest)
6225 {
6226 int i = ti_none;
6227 auto c = ref->getCombo();
6228
6229 if(ref->no_move)
6230 processed_combos[c] = true;
6231 else processed_combos[c]; //inserts element if does not exist
6232 i = move_intersection_ss(c, c, proc._first, proc._last);
6233
6234 if(i != ti_none && ref->getCombo() != 0)
6235 {
6236 if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6237 {
6238 if(ComboProtection)
6239 {
6240 if(warning_flood || warning_list.tellp() >= 65000)
6241 {
6242 if(!warning_flood)
6243 warning_list << "...\n...\n...\nmany others";
6244 warning_flood = true;
6245 }
6246 else
6247 warning_list << ref->name << '\n';
6248 }
6249 }
6250 else if(i==ti_encompass)
6251 {
6252 move_refs.emplace_back(std::move(ref));
6253 return true;
6254 }
6255 }
6256 return false;
6257 }
6258
6259 bool ComboMoveList::check_prot()
6260 {
6261 if(!ComboProtection)
6262 return true;
6263 vector<set<int> const*> subset = combo_links.subset(processed_combos);
6264 bool subset_header = false;
6265 for(int q = 0; q < 2; ++q)
6266 {
6267 bool is_dest = (q==1);
6268 if(!is_dest && !source_process)
6269 continue;
6270 ComboMoveProcess const& proc = is_dest ? dest_process : *source_process;
6271 for(auto it = subset.begin(); it != subset.end();)
6272 {
6273 auto s = *it;
6274 if(warning_flood || warning_list.tellp() >= 65000)
6275 {
6276 if(!warning_flood)
6277 warning_list << "...\n...\n...\nmany others";
6278 warning_flood = true;
6279 break;
6280 }
6281 set<int> in_set, out_set;
6282 bool no_move = is_dest;
6283 for(int c : *s)
6284 {
6285 int i = move_intersection_ss(c, c, proc._first, proc._last);
6286 if(i != ti_none)
6287 in_set.insert(c);
6288 if(i != ti_encompass)
6289 out_set.insert(c);
6290 if(!no_move)
6291 {
6292 auto it = processed_combos.find(c);
6293 if(it != processed_combos.end() && it->second)
6294 no_move = true;
6295 }
6296 }
6297 int i = in_set.empty() ? ti_none : (out_set.empty() ? ti_encompass : ti_broken);
6298 if(i == ti_encompass && !no_move)
6299 {
6300 it = subset.erase(it);
6301 continue;
6302 }
6303 if(i == ti_none)
6304 {
6305 ++it;
6306 continue;
6307 }
6308
6309 if(!subset_header)
6310 {
6311 subset_header = true;
6312 warning_list << "===== Broken Relative Combo Groups =====\n";
6313 }
6314 bool comma = false;
6315 warning_list << "In(";
6316 for(int c : in_set)
6317 {
6318 if(comma)
6319 warning_list << ",";
6320 else comma = true;
6321 warning_list << c;
6322 }
6323 warning_list << "),Out(";
6324 comma = false;
6325 for(int c : out_set)
6326 {
6327 if(comma)
6328 warning_list << ",";
6329 else comma = true;
6330 warning_list << c;
6331 }
6332 warning_list << ")\n";
6333 it = subset.erase(it);
6334 }
6335 }
6336 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Combo Warning");
6337
6338 processed_combos.clear();
6339 warning_flood = false;
6340 warning_list.clear();
6341
6342 return ret;
6343 }
6344
6345 void ComboMoveList::add_diff(int diff)
6346 {
6347 for(auto& ref : move_refs)
6348 ref->addCombo(diff);
6349 }
6350
6351 bool _handle_tile_move(TileMoveProcess dest_process, optional<TileMoveProcess> source_process, int diff, TileMoveUndo* on_undo = nullptr, std::function<void(int32_t)> every_proc = nullptr, TileMoveList::Mode mode = TileMoveList::Mode::MOVE)
6352 {
6353 bool BSZ2 = get_qr(qr_BSZELDA);
6354 bool move = source_process.has_value();
6355 TileMoveUndo local_undo;
6356 TileMoveUndo& storage = on_undo ? *on_undo : local_undo;
6357 auto& vec = storage.vec;
6358 storage.diff = diff;
6359 storage.state = false;
6360
6361 //Combos
6362 {
6363 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6364 dest_process, source_process, mode,
6365 move
6366 ? "The tiles used by the following combos will be partially cleared by the move."
6367 : "The tiles used by the following combos will be partially or completely overwritten by this process."
6368 ));
6369 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6370 {
6371 auto& cmb = combobuf[q];
6372 auto lbl = fmt::format("Combo {}{}", q, cmb.label.empty() ? ""
6373 : fmt::format(" ({})", cmb.label));
6374 movelist->add_combo(&cmb, lbl);
6375
6376 //type-specific
6377 char const* type_name = ZI.getComboTypeName(cmb.type);
6378 switch(cmb.type)
6379 {
6380 case cSPOTLIGHT:
6381 {
6382 if(!(cmb.usrflags & cflag1))
6383 break;
6384 movelist->add_tile_10k(&cmb.attributes[0], 16, 1, fmt::format("{} - Type '{}' - Beam Tiles", lbl, type_name));
6385 break;
6386 }
6387 }
6388 }
6389 if(!every_proc && !movelist->check_prot())
6390 return false;
6391 }
6392 //Items
6393 {
6394 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6395 dest_process, source_process, mode,
6396 move
6397 ? "The tiles used by the following items will be partially cleared by the move."
6398 : "The tiles used by the following items will be partially or completely overwritten by this process."
6399 ));
6400 build_bii_list(false);
6401 for(int32_t u=0; u<MAXITEMS; u++)
6402 {
6403 auto id = bii[u].i;
6404 itemdata& itm = itemsbuf[id];
6405 if(itm.family == itype_bottle)
6406 {
6407 vector<std::tuple<int,int,int>> rects;
6408 auto fr = itm.frames;
6409 for(int q = 0; q < NUM_BOTTLE_TYPES; ++q)
6410 {
6411 bottletype const& bt = QMisc.bottle_types[q];
6412 if(bt.is_blank())
6413 continue;
6414 rects.emplace_back(fr+q*fr, fr, 1);
6415 }
6416 movelist->add_tile(&itm.tile, fr, 1, fmt::format("Item {}", id),
6417 false, 0, 0, rects);
6418 }
6419 else movelist->add_tile(&itm.tile, itm.frames, 1, fmt::format("Item {}", id));
6420 }
6421 if(!every_proc && !movelist->check_prot())
6422 return false;
6423 }
6424 //Weapon sprites
6425 {
6426 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6427 dest_process, source_process, mode,
6428 move
6429 ? "The tiles used by the following weapons will be partially cleared by the move."
6430 : "The tiles used by the following weapons will be partially or completely overwritten by this process."
6431 ));
6432 build_biw_list();
6433
6434 for(int32_t u=0; u<MAXWPNS; u++)
6435 {
6436 bool ignore_frames=false;
6437 int32_t m=0;
6438
6439 auto id = biw[u].i;
6440 auto& wpn = wpnsbuf[id];
6441
6442 switch(biw[u].i)
6443 {
6444 case wSWORD:
6445 case wWSWORD:
6446 case wMSWORD:
6447 case wXSWORD:
6448 m=3+((wpnsbuf[biw[u].i].type==3)?1:0);
6449 break;
6450
6451 case wSWORDSLASH:
6452 case wWSWORDSLASH:
6453 case wMSWORDSLASH:
6454 case wXSWORDSLASH:
6455 m=4;
6456 break;
6457
6458 case iwMMeter:
6459 m=9;
6460 break;
6461
6462 case wBRANG:
6463 case wMBRANG:
6464 case wFBRANG:
6465 m=BSZ2?1:3;
6466 break;
6467
6468 case wBOOM:
6469 case wSBOOM:
6470 case ewBOOM:
6471 case ewSBOOM:
6472 ignore_frames=true;
6473 m=2;
6474 break;
6475
6476 case wWAND:
6477 m=1;
6478 break;
6479
6480 case wMAGIC:
6481 m=1;
6482 break;
6483
6484 case wARROW:
6485 case wSARROW:
6486 case wGARROW:
6487 case ewARROW:
6488 m=1;
6489 break;
6490
6491 case wHAMMER:
6492 m=8;
6493 break;
6494
6495 case wHSHEAD:
6496 m=1;
6497 break;
6498
6499 case wHSCHAIN_H:
6500 m=1;
6501 break;
6502
6503 case wHSCHAIN_V:
6504 m=1;
6505 break;
6506
6507 case wHSHANDLE:
6508 m=1;
6509 break;
6510
6511 case iwDeath:
6512 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6513 {
6514 ignore_frames = true;
6515 m=BSZ2?4:2;
6516 }
6517 break;
6518
6519 case iwSpawn:
6520 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6521 {
6522 ignore_frames = true;
6523 m=3;
6524 }
6525 break;
6526 }
6527
6528 movelist->add_tile(&wpn.tile, zc_max((ignore_frames?0:wpn.frames),1)+m,
6529 1, fmt::format("{} {}", biw[u].s, id));
6530
6531 //Tile 54+55 are "Impact (not shown in sprite list)", for u==3 "Arrow" and u==9 "Boomerang"
6532 //...these can't be updated by a move.
6533 if((u==3)||(u==9))
6534 {
6535 static int32_t impact_tiles[2] = {54,54};
6536 auto& tile = impact_tiles[u==3 ? 0 : 1];
6537 tile = 54; //dummy tile, ensure it's correct
6538 movelist->add_tile(&tile, 2, 1,
6539 fmt::format("{} Impact (not shown in sprite list)",(u==3)?"Arrow":"Boomerang"),
6540 true);
6541 }
6542 }
6543 if(!every_proc && !movelist->check_prot())
6544 return false;
6545 }
6546 //Player sprites
6547 {
6548 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6549 dest_process, source_process, mode,
6550 move
6551 ? "The tiles used by the following player sprites will be partially cleared by the move."
6552 : "The tiles used by the following player sprites will be partially or completely overwritten by this process."
6553 ));
6554 {
6555 int32_t a_style=(zinit.heroAnimationStyle);
6556 #define ADD_PLAYER_SPRITE(ref_sprite, frames, name) \
6557 do \
6558 { \
6559 movelist->add_tile(&ref_sprite[spr_tile], \
6560 (ref_sprite[spr_extend] < 2 ? 1 : 2) * frames, \
6561 ref_sprite[spr_extend] < 1 ? 1 : 2, \
6562 name, false, \
6563 ref_sprite[spr_extend] < 2 ? 0 : -1, \
6564 ref_sprite[spr_extend] < 1 ? 0 : -1); \
6565 } while(false)
6566 // + (ref_sprite[spr_extend] < 2 ? 0 : 1) //this was on some of the 'width's before... but doesn't make sense?
6567
6568 for(int32_t i=0; i<4; ++i)
6569 {
6570 ADD_PLAYER_SPRITE(walkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Walking ({})", dirstr_proper[i]));
6571 }
6572
6573 for(int32_t i=0; i<4; ++i)
6574 {
6575 ADD_PLAYER_SPRITE(slashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slashing ({})", dirstr_proper[i]));
6576 }
6577
6578 for(int32_t i=0; i<4; ++i)
6579 {
6580 ADD_PLAYER_SPRITE(stabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Stabbing ({})", dirstr_proper[i]));
6581 }
6582
6583 for(int32_t i=0; i<4; ++i)
6584 {
6585 ADD_PLAYER_SPRITE(poundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Pounding ({})", dirstr_proper[i]));
6586 }
6587
6588 for(int32_t i=0; i<2; ++i)
6589 {
6590 ADD_PLAYER_SPRITE(holdspr[0][i], 1, fmt::format("Hold (Land, {}-hand)", i+1));
6591 }
6592
6593 ADD_PLAYER_SPRITE(castingspr, 1, "Casting");
6594
6595 for(int32_t i=0; i<4; ++i)
6596 {
6597 ADD_PLAYER_SPRITE(floatspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Floating ({})", dirstr_proper[i]));
6598 }
6599
6600 for(int32_t i=0; i<4; ++i)
6601 {
6602 ADD_PLAYER_SPRITE(swimspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Swimming ({})", dirstr_proper[i]));
6603 }
6604
6605 for(int32_t i=0; i<4; ++i)
6606 {
6607 ADD_PLAYER_SPRITE(divespr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Diving ({})", dirstr_proper[i]));
6608 }
6609
6610 for(int32_t i=0; i<2; ++i)
6611 {
6612 ADD_PLAYER_SPRITE(holdspr[1][i], 1, fmt::format("Hold (Water, {}-hand)", i));
6613 }
6614
6615 for(int32_t i=0; i<4; ++i)
6616 {
6617 ADD_PLAYER_SPRITE(jumpspr[i], 3, fmt::format("Jumping ({})", dirstr_proper[i]));
6618 }
6619
6620 for(int32_t i=0; i<4; ++i)
6621 {
6622 ADD_PLAYER_SPRITE(chargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Charging ({})", dirstr_proper[i]));
6623 }
6624 for(int32_t i=0; i<4; ++i)
6625 {
6626 ADD_PLAYER_SPRITE(revslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slash 2 ({})", dirstr_proper[i]));
6627 }
6628 for(int32_t i=0; i<4; ++i)
6629 {
6630 ADD_PLAYER_SPRITE(fallingspr[i], 7, fmt::format("Falling ({})", dirstr_proper[i]));
6631 }
6632 for(int32_t i=0; i<4; ++i)
6633 {
6634 ADD_PLAYER_SPRITE(liftingspr[i], liftingspr[i][spr_frames], fmt::format("Lifting ({})", dirstr_proper[i]));
6635 }
6636 for(int32_t i=0; i<4; ++i)
6637 {
6638 ADD_PLAYER_SPRITE(liftingwalkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Lift-Walking ({})", dirstr_proper[i]));
6639 }
6640 for(int32_t i=0; i<4; ++i)
6641 {
6642 ADD_PLAYER_SPRITE(drowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Drowning ({})", dirstr_proper[i]));
6643 }
6644 for(int32_t i=0; i<4; ++i)
6645 {
6646 ADD_PLAYER_SPRITE(drowning_lavaspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Lava Drowning ({})", dirstr_proper[i]));
6647 }
6648 for(int32_t i=0; i<4; ++i)
6649 {
6650 ADD_PLAYER_SPRITE(sideswimspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swimming ({})", dirstr_proper[i]));
6651 }
6652 //69
6653 for(int32_t i=0; i<4; ++i)
6654 {
6655 ADD_PLAYER_SPRITE(sideswimslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Side-Swim Slash ({})", dirstr_proper[i]));
6656 }
6657 //73
6658 for(int32_t i=0; i<4; ++i)
6659 {
6660 ADD_PLAYER_SPRITE(sideswimstabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Stab ({})", dirstr_proper[i]));
6661 }
6662 //77
6663 for(int32_t i=0; i<4; ++i)
6664 {
6665 ADD_PLAYER_SPRITE(sideswimpoundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Pound ({})", dirstr_proper[i]));
6666 }
6667 //81
6668 for(int32_t i=0; i<4; ++i)
6669 {
6670 ADD_PLAYER_SPRITE(sideswimchargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Side-Swim Charging ({})", dirstr_proper[i]));
6671 }
6672 //85
6673 ADD_PLAYER_SPRITE(sideswimholdspr[spr_hold1], 1, "Hold (Side-Water, 1-hand)");
6674 ADD_PLAYER_SPRITE(sideswimholdspr[spr_hold2], 1, "Hold (Side-Water, 2-hand)");
6675 ADD_PLAYER_SPRITE(sideswimcastingspr, 1, "Side-Swim Casting");
6676 for(int32_t i=0; i<4; ++i)
6677 {
6678 ADD_PLAYER_SPRITE(sidedrowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swim Drowning ({})", dirstr_proper[i]));
6679 }
6680 //91
6681 }
6682 if(!every_proc && !movelist->check_prot())
6683 return false;
6684 }
6685 //Map Styles
6686 {
6687 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6688 dest_process, source_process, mode,
6689 move
6690 ? "The tiles used by the following map styles will be partially cleared by the move."
6691 : "The tiles used by the following map styles will be partially or completely overwritten by this process."
6692 ));
6693 movelist->add_tile(&QMisc.colors.blueframe_tile, 2, 2, "Frame");
6694 movelist->add_tile(&QMisc.colors.HCpieces_tile, zinit.hcp_per_hc, 1, "Heart Container Piece");
6695 movelist->add_tile(&QMisc.colors.triforce_tile, BSZ2?2:1, BSZ2?3:1, "McGuffin Fragment");
6696 movelist->add_tile(&QMisc.colors.triframe_tile, BSZ2?7:6, BSZ2?7:3, "McGuffin Frame");
6697 movelist->add_tile(&QMisc.colors.overworld_map_tile, 5, 3, "Overworld Map");
6698 movelist->add_tile(&QMisc.colors.dungeon_map_tile, 5, 3, "Dungeon Map");
6699 if(!every_proc && !movelist->check_prot())
6700 return false;
6701 }
6702 //Game Icons
6703 {
6704 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6705 dest_process, source_process, mode,
6706 move
6707 ? "The tiles used by the following game icons will be partially cleared by the move."
6708 : "The tiles used by the following game icons will be partially or completely overwritten by this process."
6709 ));
6710 for(int32_t u=0; u<4; u++)
6711 movelist->add_tile(&QMisc.icons[u], fmt::format("Game Icon {}", u));
6712 if(!every_proc && !movelist->check_prot())
6713 return false;
6714 }
6715 //DMaps
6716 {
6717 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6718 dest_process, source_process, mode,
6719 move
6720 ? "The tiles used by the following dmaps will be partially cleared by the move."
6721 : "The tiles used by the following dmaps will be partially or completely overwritten by this process."
6722 ));
6723 for(int32_t u=0; u<MAXDMAPS; u++)
6724 {
6725 auto& dm = DMaps[u];
6726 movelist->add_tile(&dm.minimap_1_tile, 5, 3, fmt::format("DMap {} - Minimap (Empty)", u));
6727 movelist->add_tile(&dm.minimap_2_tile, 5, 3, fmt::format("DMap {} - Minimap (Filled)", u));
6728 movelist->add_tile(&dm.largemap_1_tile, BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Empty)", u));
6729 movelist->add_tile(&dm.largemap_2_tile, BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Filled)", u));
6730 }
6731 if(!every_proc && !movelist->check_prot())
6732 return false;
6733 }
6734 //Enemies
6735 {
6736 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6737 dest_process, source_process, mode,
6738 move
6739 ? "The tiles used by the following enemies will be partially cleared by the move."
6740 : "The tiles used by the following enemies will be partially or completely overwritten by this process."
6741 ));
6742 build_bie_list(false);
6743 bool newtiles=get_qr(qr_NEWENEMYTILES)!=0;
6744 for(int u=0; u<eMAXGUYS; u++)
6745 {
6746 guydata& enemy=guysbuf[bie[u].i];
6747 bool darknut=false;
6748 int32_t gleeok=0;
6749
6750 if(enemy.family==eeWALK && ((enemy.flags&(inv_back|inv_front|inv_left|inv_right))!=0))
6751 darknut=true;
6752 else if(enemy.family==eeGLEEOK)
6753 {
6754 // Not certain this is the right thing to check...
6755 if(enemy.misc3==0)
6756 gleeok=1;
6757 else
6758 gleeok=2;
6759 }
6760
6761 // Dummied out enemies
6762 if(bie[u].i>=eOCTO1S && bie[u].i<e177)
6763 {
6764 if(old_guy_string[bie[u].i][strlen(old_guy_string[bie[u].i])-1]==' ')
6765 {
6766 continue;
6767 }
6768 }
6769
6770 if(newtiles)
6771 {
6772 if(guysbuf[bie[u].i].e_tile==0)
6773 {
6774 continue;
6775 }
6776
6777 vector<std::tuple<int,int,int>> rects;
6778
6779 if(darknut)
6780 {
6781 rects.emplace_back(enemy.e_tile+6*TILES_PER_ROW, enemy.e_width, enemy.e_height);
6782 }
6783 else if(enemy.family==eeGANON)
6784 {
6785 rects.emplace_back(enemy.e_tile+2*TILES_PER_ROW, 20, 4);
6786 }
6787 else if(gleeok) //No idea if this is actually *RIGHT*, but I copied what was here before faithfully -Em
6788 {
6789 for(int32_t j=0; j<4; ++j)
6790 {
6791 rects.emplace_back(
6792 TILECOL(guysbuf[bie[u].i].e_tile+(gleeok>1?-4:8)) + TILES_PER_ROW*TILEROW(guysbuf[bie[u].i].e_tile+8)+(j<<1)+(gleeok>1?1:0),
6793 4, 1);
6794 }
6795 int32_t c=TILECOL(guysbuf[bie[u].i].e_tile)+(gleeok>1?-12:0);
6796 int32_t r=TILEROW(guysbuf[bie[u].i].e_tile)+(gleeok>1?17:8);
6797 rects.emplace_back(c+TILES_PER_ROW*r, 20, 3);
6798 rects.emplace_back(c+TILES_PER_ROW*(r+3), 16, 6);
6799 }
6800 movelist->add_tile(&enemy.e_tile, enemy.e_width, enemy.e_height, fmt::format("Enemy {} ({}) 'New'", u, bie[u].s),
6801 false, 0, 0, rects);
6802 }
6803 else
6804 {
6805 if(guysbuf[bie[u].i].tile==0)
6806 {
6807 continue;
6808 }
6809 movelist->add_tile(&enemy.tile, enemy.width, enemy.height, fmt::format("Enemy {} ({}) 'Old'", u, bie[u].s));
6810
6811 if(guysbuf[bie[u].i].s_tile!=0)
6812 {
6813 movelist->add_tile(&enemy.s_tile, enemy.s_width, enemy.s_height, fmt::format("Enemy {} ({}) 'Special'", u, bie[u].s));
6814 }
6815 }
6816 }
6817 if(!every_proc && !movelist->check_prot())
6818 return false;
6819 }
6820 //Subscreens
6821 {
6822 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6823 dest_process, source_process, mode,
6824 move
6825 ? "The tiles used by the following subscreen widgets will be partially cleared by the move."
6826 : "The tiles used by the following subscreen widgets will be partially or completely overwritten by this process."
6827 ));
6828
6829 for(auto q = 0; q < subscreens_active.size(); ++q)
6830 {
6831 size_t indx = movelist->move_refs.size();
6832 subscreens_active[q].collect_tiles(*movelist.get());
6833 for(; indx < movelist->move_refs.size(); ++indx)
6834 {
6835 auto& ref = movelist->move_refs[indx];
6836 ref->name = fmt::format("Active Subscr {} - {}", q, ref->name);
6837 }
6838 }
6839 for(auto q = 0; q < subscreens_passive.size(); ++q)
6840 {
6841 size_t indx = movelist->move_refs.size();
6842 subscreens_passive[q].collect_tiles(*movelist.get());
6843 for(; indx < movelist->move_refs.size(); ++indx)
6844 {
6845 auto& ref = movelist->move_refs[indx];
6846 ref->name = fmt::format("Passive Subscr {} - {}", q, ref->name);
6847 }
6848 }
6849 for(auto q = 0; q < subscreens_overlay.size(); ++q)
6850 {
6851 size_t indx = movelist->move_refs.size();
6852 subscreens_overlay[q].collect_tiles(*movelist.get());
6853 for(; indx < movelist->move_refs.size(); ++indx)
6854 {
6855 auto& ref = movelist->move_refs[indx];
6856 ref->name = fmt::format("Overlay Subscr {} - {}", q, ref->name);
6857 }
6858 }
6859 if(!every_proc && !movelist->check_prot())
6860 return false;
6861 }
6862 //Strings
6863 {
6864 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6865 dest_process, source_process, mode,
6866 move
6867 ? "The tiles used by the following strings will be partially cleared by the move."
6868 : "The tiles used by the following strings will be partially or completely overwritten by this process."
6869 ));
6870 for(size_t q = 0; q < msg_count; ++q)
6871 {
6872 MsgStr& str = MsgStrings[q];
6873 bool fulltile = str.stringflags & STRINGFLAG_FULLTILE;
6874 movelist->add_tile(&str.tile, fulltile ? (str.w/16_zf).getCeil() : 2,
6875 fulltile ? (str.h/16_zf).getCeil() : 2, fmt::format("{} (BG): '{}'", q, util::snip(str.s,100)));
6876 movelist->add_tile(&str.portrait_tile, str.portrait_tw, str.portrait_th,
6877 fmt::format("{} (Port.): '{}'", q, util::snip(str.s,100)));
6878 }
6879 if(!every_proc && !movelist->check_prot())
6880 return false;
6881 }
6882
6883 if(source_process) //Apply the 'diff' value to all moved tiles
6884 storage.redo();
6885 if(every_proc)
6886 for(auto &list : vec)
6887 for(auto &ref : list->move_refs)
6888 ref->forEach(every_proc);
6889 return true;
6890 }
6891 bool handle_tile_move(TileMoveProcess dest_process)
6892 {
6893 return _handle_tile_move(dest_process, nullopt, 0);
6894 }
6895 bool handle_tile_move(TileMoveProcess dest_process, TileMoveProcess source_process, int diff, TileMoveUndo& on_undo)
6896 {
6897 return _handle_tile_move(dest_process, source_process, diff, &on_undo);
6898 }
6899 void for_every_used_tile(std::function<void(int32_t)> proc)
6900 {
6901 reset_combo_animations();
6902 reset_combo_animations2();
6903 TileMoveProcess all_tiles {.rect = false, ._first = 0, ._last = NEWMAXTILES-1};
6904 _handle_tile_move(all_tiles, nullopt, 0, nullptr, proc, TileMoveList::Mode::CHECK_ALL);
6905 }
6906
6907 bool _handle_combo_move(ComboMoveProcess dest_process, optional<ComboMoveProcess> source_process, int diff, ComboMoveUndo* on_undo)
6908 {
6909 bool BSZ2 = get_qr(qr_BSZELDA);
6910 bool move = source_process.has_value();
6911 ComboMoveUndo local_undo;
6912 ComboMoveUndo& storage = on_undo ? *on_undo : local_undo;
6913 auto& vec = storage.vec;
6914 auto& combo_links = storage.combo_links;
6915 storage.diff = diff;
6916 storage.state = false;
6917 //Combo relative links
6918 {
6919 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6920 {
6921 newcombo& cmb = combobuf[q];
6922 if(cmb.trigchange)
6923 combo_links.add_to(q, q+cmb.trigchange);
6924 bool next = cmb.flag == mfSECRETSNEXT;
6925 switch(cmb.type)
6926 {
6927 case cPOUND:
6928 case cLOCKBLOCK: case cLOCKBLOCK2:
6929 case cBOSSLOCKBLOCK: case cBOSSLOCKBLOCK2:
6930 case cCHEST: case cCHEST2:
6931 case cLOCKEDCHEST: case cLOCKEDCHEST2:
6932 case cBOSSCHEST: case cBOSSCHEST2:
6933 case cSTEP: case cSTEPSAME: case cSTEPALL: case cSTEPCOPY:
6934 case cSLASHNEXT: case cSLASHNEXTITEM: case cBUSHNEXT:
6935 case cSLASHNEXTTOUCHY: case cSLASHNEXTITEMTOUCHY: case cBUSHNEXTTOUCHY:
6936 case cTALLGRASSNEXT: case cCRUMBLE:
6937 next = true;
6938 break;
6939 case cCSWITCH: case cCSWITCHBLOCK:
6940 combo_links.add_to(q, q+cmb.attributes[0]);
6941 break;
6942 case cLIGHTTARGET:
6943 if(cmb.usrflags & cflag1)
6944 combo_links.add_to(q, q-1);
6945 else next = true;
6946 break;
6947 case cSTEPSFX:
6948 if((cmb.usrflags&(cflag1|cflag3)) == cflag1)
6949 next = true;
6950 break;
6951 }
6952 if(next)
6953 combo_links.add_to(q, q+1);
6954 }
6955 }
6956
6957 //This function is expensive! Any optimizations possible should be made. -Em
6958
6959 //OPT: Check for a 0-val preemptively, to avoid processing the fmt::format strings
6960 #define ADDC(ptr, ...) \
6961 if(*ptr) movelist->add_combo(ptr, __VA_ARGS__);
6962 #define ADDC_10k(ptr, ...) \
6963 if(*ptr) movelist->add_combo_10k(ptr, __VA_ARGS__);
6964 //Combos
6965 {
6966 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
6967 combo_links, dest_process, source_process,
6968 move
6969 ? "The combos used by the following combos will be partially cleared by the move."
6970 : "The combos used by the following combos will be partially or completely overwritten by this process."
6971 ));
6972 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6973 {
6974 newcombo& cmb = combobuf[q];
6975 auto lbl = fmt::format("{}{}", q, cmb.label.empty() ? ""
6976 : fmt::format(" ({})", cmb.label));
6977 ADDC(&cmb.nextcombo, fmt::format("{} - Combo Cycle", lbl));
6978 ADDC(&cmb.liftcmb, fmt::format("{} - Lift Combo", lbl));
6979 ADDC(&cmb.liftundercmb, fmt::format("{} - Lift Undercombo", lbl));
6980 ADDC(&cmb.prompt_cid, fmt::format("{} - Triggers ButtonPrompt", lbl));
6981
6982 //type-specific
6983 char const* type_name = ZI.getComboTypeName(cmb.type);
6984 switch(cmb.type)
6985 {
6986 case cLOCKEDCHEST: case cBOSSCHEST:
6987 if(cmb.usrflags & cflag13)
6988 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
6989 [[fallthrough]];
6990 case cCHEST:
6991 if(cmb.usrflags & cflag13)
6992 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
6993 break;
6994 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
6995 if(cmb.usrflags & cflag13)
6996 {
6997 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
6998 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
6999 }
7000 break;
7001 case cSIGNPOST:
7002 if(cmb.usrflags & cflag13)
7003 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7004 break;
7005 case cBUTTONPROMPT:
7006 if(cmb.usrflags & cflag13)
7007 ADDC_10k(&cmb.attributes[0], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7008 break;
7009 }
7010 }
7011
7012 if(!movelist->check_prot())
7013 return false;
7014 }
7015 //Door Combo Sets
7016 {
7017 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7018 combo_links, dest_process, source_process,
7019 move
7020 ? "The combos used by the following screens will be partially cleared by the move."
7021 : "The combos used by the following screens will be partially or completely overwritten by this process."
7022 ));
7023 static const char* door_names[9] = {
7024 "Wall", "Locked", "Shuttered", "Boss", "Bombed", "Open", "Unlocked", "Open Shuttered", "Open Boss"
7025 };
7026 for(int32_t i=0; i<MAXDOORCOMBOSETS; i++)
7027 {
7028 auto& dcs = DoorComboSets[i];
7029 for(int32_t j=0; j<9; j++)
7030 {
7031 if(j<4)
7032 {
7033 ADDC(&dcs.walkthroughcombo[j], fmt::format("{} ({}): Walk-Through {}", i, dcs.name, j));
7034
7035 if(j<3)
7036 {
7037 if(j<2)
7038 {
7039 ADDC(&dcs.bombdoorcombo_u[j], fmt::format("{} ({}): Unused? bombdoorcombo_u {}", i, dcs.name, j));
7040 ADDC(&dcs.bombdoorcombo_d[j], fmt::format("{} ({}): Unused? bombdoorcombo_d {}", i, dcs.name, j));
7041 }
7042 ADDC(&dcs.bombdoorcombo_l[j], fmt::format("{} ({}): Unused? bombdoorcombo_l {}", i, dcs.name, j));
7043 ADDC(&dcs.bombdoorcombo_r[j], fmt::format("{} ({}): Unused? bombdoorcombo_r {}", i, dcs.name, j));
7044 }
7045 }
7046
7047 for(int32_t k=0; k<6; k++)
7048 {
7049 if(k<4)
7050 {
7051 ADDC(&dcs.doorcombo_u[j][k], fmt::format("{} ({}): Top, {} #{}", i, dcs.name, door_names[j], k));
7052 ADDC(&dcs.doorcombo_d[j][k], fmt::format("{} ({}): Bottom, {} #{}", i, dcs.name, door_names[j], k));
7053 }
7054
7055 ADDC(&dcs.doorcombo_l[j][k], fmt::format("{} ({}): Left, {} #{}", i, dcs.name, door_names[j], k));
7056 ADDC(&dcs.doorcombo_r[j][k], fmt::format("{} ({}): Right, {} #{}", i, dcs.name, door_names[j], k));
7057 }
7058 }
7059 }
7060
7061 if(!movelist->check_prot())
7062 return false;
7063 }
7064 //Combo Pools
7065 {
7066 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7067 combo_links, dest_process, source_process,
7068 move
7069 ? "The combos used by the following combo pools will be partially cleared by the move."
7070 : "The combos used by the following combo pools will be partially or completely overwritten by this process."
7071 ));
7072 for(auto q = 0; q < MAXCOMBOPOOLS; ++q)
7073 {
7074 combo_pool& pool = combo_pools[q];
7075 int idx = 0;
7076 for(cpool_entry& cp : pool.combos)
7077 ADDC(&cp.cid, fmt::format("{} index {}", q, idx++));
7078 }
7079
7080 if(!movelist->check_prot())
7081 return false;
7082 }
7083 //Auto Combos
7084 {
7085 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7086 combo_links, dest_process, source_process,
7087 move
7088 ? "The combos used by the following autocombos will be partially cleared by the move."
7089 : "The combos used by the following autocombos will be partially or completely overwritten by this process."
7090 ));
7091 for (auto q = 0; q < MAXAUTOCOMBOS; ++q)
7092 {
7093 combo_auto& cauto = combo_autos[q];
7094 int idx = 0;
7095 for (autocombo_entry& ac : cauto.combos)
7096 ADDC(&ac.cid, fmt::format("{} index {}", q, idx++));
7097 ADDC(&cauto.cid_erase, fmt::format("{} Erase Combo", q));
7098 ADDC(&cauto.cid_display, fmt::format("{} Display Combo", q));
7099 }
7100
7101 if(!movelist->check_prot())
7102 return false;
7103 }
7104 //Combo Aliases
7105 {
7106 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7107 combo_links, dest_process, source_process,
7108 move
7109 ? "The combos used by the following aliases will be partially cleared by the move."
7110 : "The combos used by the following aliases will be partially or completely overwritten by this process."
7111 ));
7112 for(int32_t i=0; i<MAXCOMBOALIASES; i++)
7113 {
7114 //dimensions are 1 less than you would expect -DD
7115 int32_t count=(comboa_lmasktotal(combo_aliases[i].layermask)+1)*(combo_aliases[i].width+1)*(combo_aliases[i].height+1);
7116
7117 for(int32_t j=0; j<count; j++)
7118 {
7119 ADDC(&combo_aliases[i].combos[j], fmt::format("{} index {}", i, j));
7120 }
7121 }
7122
7123 if(!movelist->check_prot())
7124 return false;
7125 }
7126 //Favorite Combos
7127 {
7128 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7129 combo_links, dest_process, source_process,
7130 move
7131 ? "The combos used by the following favorite combos will be partially cleared by the move."
7132 : "The combos used by the following favorite combos will be partially or completely overwritten by this process."
7133 ));
7134 for(int32_t i=0; i<MAXFAVORITECOMBOS; i++)
7135 {
7136 if(favorite_combo_modes[i] != dm_normal) //don't hit pools/aliases/autos, only combos!
7137 continue;
7138 ADDC(&favorite_combos[i], fmt::format("Favorite {}", i));
7139 }
7140
7141 if(!movelist->check_prot())
7142 return false;
7143 }
7144 //Bottle Shops
7145 {
7146 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7147 combo_links, dest_process, source_process,
7148 move
7149 ? "The combos used by the following bottle shops will be partially cleared by the move."
7150 : "The combos used by the following bottle shops will be partially or completely overwritten by this process."
7151 ));
7152 for(auto q = 0; q < 256; ++q)
7153 for(auto p = 0; p < 3; ++p)
7154 ADDC(&QMisc.bottle_shop_types[q].comb[p], fmt::format("{} slot {}", q, p));
7155
7156 if(!movelist->check_prot())
7157 return false;
7158 }
7159 //Screens //EXPENSIVE! DO THIS LAST!
7160 {
7161 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7162 combo_links, dest_process, source_process,
7163 move
7164 ? "The combos used by the following screens will be partially cleared by the move."
7165 : "The combos used by the following screens will be partially or completely overwritten by this process."
7166 ));
7167
7168 for(int32_t i=0; i<map_count && i<MAXMAPS; i++)
7169 {
7170 for(int32_t j=0; j<MAPSCRS; j++)
7171 {
7172 mapscr& scr = TheMaps[i*MAPSCRS+j];
7173
7174 if(!(scr.valid&mVALID))
7175 continue;
7176
7177 ADDC(&scr.undercombo, fmt::format("{}x{:02X} - UnderCombo", i, j));
7178 for(int32_t k=0; k<176; k++)
7179 ADDC(&scr.data[k], fmt::format("{}x{:02X} - Pos {}", i, j, k));
7180
7181 for(int32_t k=0; k<128; k++)
7182 ADDC(&scr.secretcombo[k], fmt::format("{}x{:02X} - SecretCombo {}", i, j, k));
7183
7184 word maxffc = scr.numFFC();
7185 for(word k=0; k<maxffc; k++)
7186 {
7187 ffcdata& ffc = scr.ffcs[k];
7188 ADDC(&ffc.data, fmt::format("{}x{:02X} - FFC {}", i, j, k+1));
7189 }
7190 }
7191 }
7192
7193 if(!movelist->check_prot())
7194 return false;
7195 }
7196 if(source_process) //Apply the 'diff' value to all moved combos
7197 storage.redo();
7198 return true;
7199 }
7200
7201 bool handle_combo_move(ComboMoveProcess dest_process)
7202 {
7203 return _handle_combo_move(dest_process, nullopt, 0, nullptr);
7204 }
7205 bool handle_combo_move(ComboMoveProcess dest_process, ComboMoveProcess source_process, int diff, ComboMoveUndo& on_undo)
7206 {
7207 return _handle_combo_move(dest_process, source_process, diff, &on_undo);
7208 }
7209 void register_used_tiles()
7210 {
7211 memset(used_tile_table, 0, sizeof(used_tile_table));
7212 for_every_used_tile([&](int tile)
7213 {
7214 used_tile_table[tile] = true;
7215 });
7216 }
7217
7218 bool overlay_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move, int32_t cs, bool backwards)
7219 {
7220 bool ctrl=(CHECK_CTRL_CMD);
7221 bool copied=false;
7222 copied=overlay_tiles_united(tile,tile2,copy,copycnt,rect_sel,move,cs,backwards);
7223
7224 if(copied)
7225 {
7226 saved=false;
7227 }
7228
7229 return copied;
7230 }
7231
7232 bool overlay_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move, int32_t cs, bool backwards)
7233 {
7234 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7235 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7236
7237 // if tile>tile2 then swap them
7238 if(tile>tile2)
7239 {
7240 zc_swap(tile, tile2);
7241 }
7242
7243 // alt=copy from right
7244 // shift=copy from bottom
7245
7246 int32_t copies=copycnt;
7247 int32_t dest_first=tile;
7248 int32_t dest_last=tile2;
7249 int32_t src_first=copy;
7250 int32_t src_last=copy+copies-1;
7251
7252 int32_t dest_top=0;
7253 int32_t dest_bottom=0;
7254 int32_t src_top=0;
7255 int32_t src_bottom=0;
7256 int32_t src_left=0, src_right=0;
7257 int32_t src_width=0, src_height=0;
7258 int32_t dest_left=0, dest_right=0;
7259 int32_t dest_width=0, dest_height=0;
7260 int32_t rows=0, cols=0;
7261
7262 if(rect)
7263 {
7264 dest_top=TILEROW(dest_first);
7265 dest_bottom=TILEROW(dest_last);
7266 src_top=TILEROW(src_first);
7267 src_bottom=TILEROW(src_last);
7268
7269 src_left= zc_min(TILECOL(src_first),TILECOL(src_last));
7270 src_right=zc_max(TILECOL(src_first),TILECOL(src_last));
7271 src_first=(src_top * TILES_PER_ROW)+src_left;
7272 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7273
7274 dest_left= zc_min(TILECOL(dest_first),TILECOL(dest_last));
7275 dest_right=zc_max(TILECOL(dest_first),TILECOL(dest_last));
7276 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7277 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7278
7279 //if no dest range set, then set one
7280 if((dest_first==dest_last)&&(src_first!=src_last))
7281 {
7282 if(alt)
7283 {
7284 dest_left=dest_right-(src_right-src_left);
7285 }
7286 else
7287 {
7288 dest_right=dest_left+(src_right-src_left);
7289 }
7290
7291 if(shift)
7292 {
7293 dest_top=dest_bottom-(src_bottom-src_top);
7294 }
7295 else
7296 {
7297 dest_bottom=dest_top+(src_bottom-src_top);
7298 }
7299
7300 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7301 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7302 }
7303 else
7304 {
7305 if(dest_right-dest_left<src_right-src_left) //destination is shorter than source
7306 {
7307 if(alt) //copy from right tile instead of left
7308 {
7309 src_left=src_right-(dest_right-dest_left);
7310 }
7311 else //copy from left tile
7312 {
7313 src_right=src_left+(dest_right-dest_left);
7314 }
7315 }
7316 else if(dest_right-dest_left>src_right-src_left) //destination is longer than source
7317 {
7318 if(alt) //copy from right tile instead of left
7319 {
7320 dest_left=dest_right-(src_right-src_left);
7321 }
7322 else //copy from left tile
7323 {
7324 dest_right=dest_left+(src_right-src_left);
7325 }
7326 }
7327
7328 if(dest_bottom-dest_top<src_bottom-src_top) //destination is shorter than source
7329 {
7330 if(shift) //copy from bottom tile instead of top
7331 {
7332 src_top=src_bottom-(dest_bottom-dest_top);
7333 }
7334 else //copy from top tile
7335 {
7336 src_bottom=src_top+(dest_bottom-dest_top);
7337 }
7338 }
7339 else if(dest_bottom-dest_top>src_bottom-src_top) //destination is longer than source
7340 {
7341 if(shift) //copy from bottom tile instead of top
7342 {
7343 dest_top=dest_bottom-(src_bottom-src_top);
7344 }
7345 else //copy from top tile
7346 {
7347 dest_bottom=dest_top+(src_bottom-src_top);
7348 }
7349 }
7350
7351 src_first=(src_top * TILES_PER_ROW)+src_left;
7352 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7353 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7354 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7355 }
7356
7357 cols=src_right-src_left+1;
7358 rows=src_bottom-src_top+1;
7359
7360 dest_width=dest_right-dest_left+1;
7361 dest_height=dest_bottom-dest_top+1;
7362 src_width=src_right-src_left+1;
7363 src_height=src_bottom-src_top+1;
7364
7365 }
7366 else //!rect
7367 {
7368 //if no dest range set, then set one
7369 if((dest_first==dest_last)&&(src_first!=src_last))
7370 {
7371 if(alt)
7372 {
7373 dest_first=dest_last-(src_last-src_first);
7374 }
7375 else
7376 {
7377 dest_last=dest_first+(src_last-src_first);
7378 }
7379 }
7380 else
7381 {
7382 if(dest_last-dest_first<src_last-src_first) //destination is shorter than source
7383 {
7384 if(alt) //copy from last tile instead of first
7385 {
7386 src_first=src_last-(dest_last-dest_first);
7387 }
7388 else //copy from first tile
7389 {
7390 src_last=src_first+(dest_last-dest_first);
7391 }
7392 }
7393 else if(dest_last-dest_first>src_last-src_first) //destination is longer than source
7394 {
7395 if(alt) //copy from last tile instead of first
7396 {
7397 dest_first=dest_last-(src_last-src_first);
7398 }
7399 else //copy from first tile
7400 {
7401 dest_last=dest_first+(src_last-src_first);
7402 }
7403 }
7404 }
7405
7406 copies=dest_last-dest_first+1;
7407 }
7408
7409
7410
7411 char buf2[80], buf3[80], buf4[80];
7412 sprintf(buf2, " ");
7413 sprintf(buf3, " ");
7414 sprintf(buf4, " ");
7415
7416 // warn if range extends beyond last tile
7417 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7418
7419 if(dest_last>=NEWMAXTILES)
7420 {
7421 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7422 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7423 return false;
7424 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7425 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7426 // {
7427 // return false;
7428 // }
7429 }
7430
7431
7432 TileMoveUndo on_undo;
7433 // Overwrite warnings
7434 TileMoveProcess dest{rect, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last};
7435 if(move)
7436 {
7437 TileMoveProcess src{rect, src_left, src_top, src_width, src_height, src_first, src_last};
7438 if(!handle_tile_move(dest, src, dest_first-src_first, on_undo))
7439 return false;
7440 }
7441 else
7442 {
7443 if(!handle_tile_move(dest))
7444 return false;
7445 }
7446 // copy tiles and delete if needed (move)
7447
7448 {
7449 go_tiles();
7450
7451 int32_t diff=dest_first-src_first;
7452
7453 if(rect)
7454 {
7455 for(int32_t r=0; r<rows; ++r)
7456 {
7457 for(int32_t c=0; c<cols; ++c)
7458 {
7459 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
7460 int32_t st=(src_first+((r*TILES_PER_ROW)+c));
7461
7462 if(dt>=NEWMAXTILES)
7463 continue;
7464
7465 overlay_tile(newtilebuf,dt,st,cs,backwards);
7466
7467 }
7468 }
7469 }
7470 else
7471 {
7472 for(int32_t c=0; c<copies; ++c)
7473 {
7474 int32_t dt=(dest_first+c);
7475 int32_t st=(src_first+c);
7476
7477 if(dt>=NEWMAXTILES)
7478 continue;
7479
7480 overlay_tile(newtilebuf,dt,st,cs,backwards);
7481
7482 if(move)
7483 {
7484 if(st<dest_first||st>(dest_first+c-1))
7485 reset_tile(newtilebuf, st, tf4Bit);
7486 }
7487 }
7488 }
7489 }
7490
7491 //now that tiles have moved, fix these buffers -DD
7492 register_blank_tiles();
7493 register_used_tiles();
7494
7495 if(move)
7496 last_tile_move_list = std::move(on_undo);
7497 return true;
7498 }
7499 //
7500 bool do_movetile_united(tile_move_data const& tmd)
7501 {
7502 char buf2[80], buf3[80], buf4[80];
7503 sprintf(buf2, " ");
7504 sprintf(buf3, " ");
7505 sprintf(buf4, " ");
7506
7507 // warn if range extends beyond last tile
7508 sprintf(buf4, "Some tiles will not be %s", tmd.move?"moved.":"copied.");
7509
7510 if(tmd.dest_last>=NEWMAXTILES)
7511 {
7512 sprintf(buf4, "%s operation cancelled.", tmd.move?"Move":"Copy");
7513 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7514 return false;
7515 }
7516
7517 TileMoveUndo on_undo;
7518 // Overwrite warnings
7519 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7520 if(tmd.move)
7521 {
7522 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7523 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7524 return false;
7525 }
7526 else
7527 {
7528 if(!handle_tile_move(dest))
7529 return false;
7530 }
7531
7532 // copy tiles and delete if needed (tmd.move)
7533 {
7534 go_tiles();
7535
7536 if(tmd.rect)
7537 {
7538 for(int32_t r=0; r<tmd.rows; ++r)
7539 {
7540 for(int32_t c=0; c<tmd.cols; ++c)
7541 {
7542 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7543 int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7544
7545 if(dt>=NEWMAXTILES)
7546 continue;
7547
7548 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7549
7550 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7551 {
7552 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7553 }
7554
7555 if(tmd.move)
7556 {
7557 if((st<tmd.dest_first||st>tmd.dest_first+((tmd.rows-1)*TILES_PER_ROW)+(tmd.cols-1)))
7558 reset_tile(newtilebuf, st, tf4Bit);
7559 else
7560 {
7561 int32_t destLeft=tmd.dest_first%TILES_PER_ROW;
7562 int32_t destRight=(tmd.dest_first+tmd.cols-1)%TILES_PER_ROW;
7563 if(destLeft<=destRight)
7564 {
7565 if(st%TILES_PER_ROW<destLeft || st%TILES_PER_ROW>destRight)
7566 reset_tile(newtilebuf, st, tf4Bit);
7567 }
7568 else // Wrapped around
7569 {
7570 if(st%TILES_PER_ROW<destLeft && st%TILES_PER_ROW>destRight)
7571 reset_tile(newtilebuf, st, tf4Bit);
7572 }
7573 }
7574 }
7575 }
7576 }
7577 }
7578 else
7579 {
7580 for(int32_t c=0; c<tmd.copies; ++c)
7581 {
7582 int32_t dt=(tmd.dest_first+c);
7583 int32_t st=(tmd.src_first+c);
7584
7585 if(dt>=NEWMAXTILES)
7586 continue;
7587
7588 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7589
7590 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7591 {
7592 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7593 }
7594
7595 if(tmd.move)
7596 {
7597 if(st<tmd.dest_first||st>(tmd.dest_first+c-1))
7598 reset_tile(newtilebuf, st, tf4Bit);
7599 }
7600 }
7601 }
7602 }
7603
7604 //now that tiles have moved, fix these buffers -DD
7605 register_blank_tiles();
7606 register_used_tiles();
7607
7608 if(tmd.move)
7609 last_tile_move_list = std::move(on_undo);
7610 return true;
7611 }
7612
7613 bool copy_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7614 {
7615 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7616 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7617
7618 // if tile>tile2 then swap them
7619 if(tile>tile2)
7620 {
7621 zc_swap(tile, tile2);
7622 }
7623
7624 // alt=copy from right
7625 // shift=copy from bottom
7626 tile_move_data tmd;
7627
7628 tmd.copies=copycnt;
7629 tmd.dest_first=tile;
7630 tmd.dest_last=tile2;
7631 tmd.src_first=copy;
7632 tmd.src_last=copy+tmd.copies-1;
7633 tmd.rect = rect;
7634 tmd.move = move;
7635
7636 if(rect)
7637 {
7638 tmd.dest_top=TILEROW(tmd.dest_first);
7639 tmd.dest_bottom=TILEROW(tmd.dest_last);
7640 tmd.src_top=TILEROW(tmd.src_first);
7641 tmd.src_bottom=TILEROW(tmd.src_last);
7642
7643 tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7644 tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7645 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7646 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7647
7648 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7649 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7650 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7651 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7652
7653 //if no dest range set, then set one
7654 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7655 {
7656 if(alt)
7657 {
7658 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7659 }
7660 else
7661 {
7662 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7663 }
7664
7665 if(shift)
7666 {
7667 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7668 }
7669 else
7670 {
7671 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7672 }
7673
7674 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7675 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7676 }
7677 else
7678 {
7679 if(tmd.dest_right-tmd.dest_left<tmd.src_right-tmd.src_left) //destination is shorter than source
7680 {
7681 if(alt) //copy from right tile instead of left
7682 {
7683 tmd.src_left=tmd.src_right-(tmd.dest_right-tmd.dest_left);
7684 }
7685 else //copy from left tile
7686 {
7687 tmd.src_right=tmd.src_left+(tmd.dest_right-tmd.dest_left);
7688 }
7689 }
7690 else if(tmd.dest_right-tmd.dest_left>tmd.src_right-tmd.src_left) //destination is longer than source
7691 {
7692 if(alt) //copy from right tile instead of left
7693 {
7694 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7695 }
7696 else //copy from left tile
7697 {
7698 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7699 }
7700 }
7701
7702 if(tmd.dest_bottom-tmd.dest_top<tmd.src_bottom-tmd.src_top) //destination is shorter than source
7703 {
7704 if(shift) //copy from bottom tile instead of top
7705 {
7706 tmd.src_top=tmd.src_bottom-(tmd.dest_bottom-tmd.dest_top);
7707 }
7708 else //copy from top tile
7709 {
7710 tmd.src_bottom=tmd.src_top+(tmd.dest_bottom-tmd.dest_top);
7711 }
7712 }
7713 else if(tmd.dest_bottom-tmd.dest_top>tmd.src_bottom-tmd.src_top) //destination is longer than source
7714 {
7715 if(shift) //copy from bottom tile instead of top
7716 {
7717 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7718 }
7719 else //copy from top tile
7720 {
7721 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7722 }
7723 }
7724
7725 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7726 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7727 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7728 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7729 }
7730
7731 tmd.cols=tmd.src_right-tmd.src_left+1;
7732 tmd.rows=tmd.src_bottom-tmd.src_top+1;
7733
7734 tmd.dest_width=tmd.dest_right-tmd.dest_left+1;
7735 tmd.dest_height=tmd.dest_bottom-tmd.dest_top+1;
7736 tmd.src_width=tmd.src_right-tmd.src_left+1;
7737 tmd.src_height=tmd.src_bottom-tmd.src_top+1;
7738
7739 }
7740 else //!rect
7741 {
7742 //if no dest range set, then set one
7743 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7744 {
7745 if(alt)
7746 {
7747 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7748 }
7749 else
7750 {
7751 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7752 }
7753 }
7754 else
7755 {
7756 if(tmd.dest_last-tmd.dest_first<tmd.src_last-tmd.src_first) //destination is shorter than source
7757 {
7758 if(alt) //copy from last tile instead of first
7759 {
7760 tmd.src_first=tmd.src_last-(tmd.dest_last-tmd.dest_first);
7761 }
7762 else //copy from first tile
7763 {
7764 tmd.src_last=tmd.src_first+(tmd.dest_last-tmd.dest_first);
7765 }
7766 }
7767 else if(tmd.dest_last-tmd.dest_first>tmd.src_last-tmd.src_first) //destination is longer than source
7768 {
7769 if(alt) //copy from last tile instead of first
7770 {
7771 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7772 }
7773 else //copy from first tile
7774 {
7775 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7776 }
7777 }
7778 }
7779
7780 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7781 }
7782
7783 return do_movetile_united(tmd);
7784 }
7785
7786 //
7787
7788 bool copy_tiles_united_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7789 {
7790 assert(!move); //not implemented
7791
7792 // if tile>tile2 then swap them
7793 if(tile>tile2)
7794 {
7795 zc_swap(tile, tile2);
7796 }
7797
7798 tile_move_data tmd;
7799 tmd.copies=copycnt;
7800 tmd.dest_first=tile;
7801 tmd.dest_last=tile2;
7802 tmd.src_first=copy;
7803 tmd.src_last=copy+tmd.copies-1;
7804
7805
7806
7807 if(rect)
7808 {
7809 tmd.dest_top=TILEROW(tmd.dest_first);
7810 tmd.dest_bottom=TILEROW(tmd.dest_last);
7811 //tmd.src_top=TILEROW(tmd.src_first);
7812 //tmd.src_bottom=TILEROW(tmd.src_last);
7813
7814 //tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7815 //tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7816 //tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7817 //tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7818
7819 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7820 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7821 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7822 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7823
7824
7825
7826
7827 tmd.dest_width=tmd.dest_right-tmd.dest_left;
7828 tmd.dest_height=tmd.dest_bottom-tmd.dest_top;
7829
7830 tmd.cols=tmd.dest_width+1;
7831 tmd.rows=tmd.dest_height+1;
7832
7833 al_trace("tmd.rows: %d\n", tmd.rows);
7834 al_trace("tmd.cols: %d\n", tmd.cols);
7835
7836
7837 }
7838 else //!rect
7839 {
7840 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7841 }
7842
7843
7844
7845 char buf2[80], buf3[80], buf4[80];
7846 sprintf(buf2, " ");
7847 sprintf(buf3, " ");
7848 sprintf(buf4, " ");
7849
7850 // warn if range extends beyond last tile
7851 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7852
7853 if(tmd.dest_last>=NEWMAXTILES)
7854 {
7855 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7856 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7857 return false;
7858 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7859 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7860 // {
7861 // return false;
7862 // }
7863 }
7864
7865 TileMoveUndo on_undo;
7866 // Overwrite warnings
7867 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7868 if(tmd.move)
7869 {
7870 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7871 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7872 return false;
7873 }
7874 else
7875 {
7876 if(!handle_tile_move(dest))
7877 return false;
7878 }
7879
7880 // copy tiles and delete if needed (move)
7881
7882 {
7883 go_tiles();
7884
7885 int32_t diff=tmd.dest_first-tmd.src_first;
7886
7887 if(rect)
7888 {
7889 al_trace("floodfill, rect\n");
7890 al_trace("tmd.rows: %d\n", tmd.rows);
7891 al_trace("tmd.cols: %d\n", tmd.cols);
7892 for(int32_t r=0; r<tmd.rows; ++r)
7893 {
7894 for(int32_t c=0; c<tmd.cols; ++c)
7895 {
7896 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7897 //int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7898
7899 if(dt>=NEWMAXTILES)
7900 continue;
7901
7902 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
7903
7904 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
7905 {
7906 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
7907 }
7908 }
7909 }
7910 }
7911 else
7912 {
7913 for(int32_t c=0; c<tmd.copies; ++c)
7914 {
7915 int32_t dt=(tmd.dest_first+c);
7916 int32_t st=(tmd.src_first+c);
7917
7918 if(dt>=NEWMAXTILES)
7919 continue;
7920
7921 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
7922
7923 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
7924 {
7925 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
7926 }
7927
7928 }
7929 }
7930 }
7931
7932 //now that tiles have moved, fix these buffers -DD
7933 register_blank_tiles();
7934 register_used_tiles();
7935
7936 if(tmd.move)
7937 last_tile_move_list = std::move(on_undo);
7938 return true;
7939 }
7940 //
7941
7942 bool copy_tiles_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
7943 {
7944 al_trace("Floodfill Psste\n");
7945 bool ctrl=(CHECK_CTRL_CMD);
7946 bool copied=false;
7947 copied=copy_tiles_united_floodfill(tile,tile2,copy,copycnt,rect_sel,move);
7948
7949 if(copied)
7950 {
7951 if(!ctrl)
7952 {
7953 copy=-1;
7954 tile2=tile;
7955 }
7956
7957 saved=false;
7958 }
7959
7960 return copied;
7961 }
7962
7963 bool copy_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
7964 {
7965 bool ctrl=(CHECK_CTRL_CMD);
7966 bool copied=false;
7967 copied=copy_tiles_united(tile,tile2,copy,copycnt,rect_sel,move);
7968
7969 if(copied)
7970 {
7971 if(!ctrl)
7972 {
7973 copy=-1;
7974 tile2=tile;
7975 }
7976
7977 saved=false;
7978 }
7979
7980 return copied;
7981 }
7982
7983 bool scale_or_rotate_tiles(int32_t &tile, int32_t &tile2, int32_t &cs, bool rotate)
7984 {
7985 // if tile>tile2 then swap them
7986 if(tile>tile2)
7987 {
7988 zc_swap(tile, tile2);
7989 }
7990 int32_t src_top = TILEROW(tile);
7991 int32_t src_bottom = TILEROW(tile2);
7992 int32_t src_left = zc_min(TILECOL(tile),TILECOL(tile2));
7993 int32_t src_right = zc_max(TILECOL(tile),TILECOL(tile2));
7994 int32_t src_first = (src_top * TILES_PER_ROW)+src_left;
7995 int32_t src_last = (src_bottom*TILES_PER_ROW)+src_right;
7996
7997 int32_t src_width = src_right-src_left+1,
7998 src_height = src_bottom-src_top+1;
7999 int32_t dest_width = src_width, dest_height = src_height;
8000 zfix dest_rot = 0_zf;
8001 if(rotate)
8002 RotateTileDialog(&dest_width, &dest_height, &dest_rot).show();
8003 else
8004 ScaleTileDialog(&dest_width, &dest_height).show();
8005 if (rotate)
8006 {
8007 if (dest_rot == 0) return false;
8008 }
8009 else
8010 {
8011 if (dest_width == src_width && dest_height == src_height) return false; //no scaling
8012 }
8013 dest_width = vbound(dest_width, 1, 20);
8014 dest_height = vbound(dest_height, 1, 20);
8015
8016 int32_t dest_top = src_top;
8017 int32_t dest_bottom = src_top+dest_height-1;
8018 int32_t dest_left = src_left;
8019 int32_t dest_right = src_left+dest_width-1;
8020 int32_t dest_first = src_first;
8021 int32_t dest_last = (dest_bottom*TILES_PER_ROW)+dest_right;
8022
8023
8024 if(dest_last>=NEWMAXTILES)
8025 {
8026 InfoDialog("Destination Error", "The destination extends beyond the last available tile row. Scale operation cancelled.").show();
8027 return false;
8028 }
8029
8030 // Overwrite warnings
8031 if(!handle_tile_move({true, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last}))
8032 return false;
8033
8034 //Do the rotate
8035 {
8036 go_tiles();
8037
8038 int32_t diff=dest_first-src_first;
8039 BITMAP *srcbmp = create_bitmap_ex(8,src_width*16,src_height*16),
8040 *destbmp = create_bitmap_ex(8,dest_width*16,dest_height*16);
8041 clear_bitmap(srcbmp); clear_bitmap(destbmp);
8042 overtileblock16(srcbmp, src_first, 0, 0, src_width, src_height, cs, 0);
8043 bool is8bit = newtilebuf[src_first].format == tf8Bit;
8044 if (rotate)
8045 {
8046 rotate_sprite(destbmp, srcbmp, 0, 0, ftofix(dest_rot * 0.7111111111111));
8047 }
8048 else
8049 {
8050 stretch_blit(srcbmp, destbmp, 0, 0, srcbmp->w, srcbmp->h,
8051 0, 0, destbmp->w, destbmp->h);
8052 }
8053 int32_t mhei = zc_max(src_height,dest_height),
8054 mwid = zc_max(src_width, dest_width);
8055 for(int32_t r=0; r<mhei; ++r)
8056 {
8057 for(int32_t c=0; c<mwid; ++c)
8058 {
8059 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
8060
8061 if(dt>=NEWMAXTILES)
8062 continue;
8063 if(r < dest_height && c < dest_width)
8064 {
8065 write_tile(newtilebuf, destbmp, dt, c*16, r*16, is8bit, false);
8066 }
8067 else reset_tile(newtilebuf, dt, tf4Bit);
8068 }
8069 }
8070 }
8071
8072 register_blank_tiles();
8073 register_used_tiles();
8074 return true;
8075 }
8076
8077 void copy_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool masscopy)
8078 {
8079 //these 2 shouldn't be needed, but just to be safe...
8080 reset_combo_animations();
8081 reset_combo_animations2();
8082
8083 if(tile2<tile)
8084 {
8085 zc_swap(tile,tile2);
8086 }
8087
8088 auto first = tile;
8089 auto last = masscopy ? tile2 : first + copycnt-1;
8090 if(!handle_combo_move({first,last}))
8091 return;
8092
8093 if(!masscopy)
8094 {
8095 if(tile==copy)
8096 {
8097 copy=-1;
8098 tile2=tile;
8099 return;
8100 }
8101
8102 // go_combos(); // commented because caller does it for us
8103 //if copying to an earlier combo, copy from left to right
8104 //otherwise, copy from right to left
8105 for(int32_t t=(tile<copy)?0:(copycnt-1); (tile<copy)?(t<copycnt):(t>=0); (tile<copy)?(t++):(t--))
8106 {
8107 if(tile+t < MAXCOMBOS)
8108 {
8109 combobuf[tile+t]=combobuf[copy+t];
8110 }
8111 }
8112
8113 copy=-1;
8114 tile2=tile;
8115 saved=false;
8116 }
8117 else
8118 {
8119 // go_combos();
8120 int32_t src=copy, dest=tile;
8121
8122 do
8123 {
8124 combobuf[dest]=combobuf[src];
8125 ++src;
8126 ++dest;
8127
8128 if((src-copy)==copycnt) src=copy;
8129 }
8130 while(dest<=tile2);
8131
8132 copy=-1;
8133 tile2=tile;
8134 saved=false;
8135 }
8136
8137 setup_combo_animations();
8138 setup_combo_animations2();
8139 }
8140
8141 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing)
8142 {
8143 reset_combo_animations();
8144 reset_combo_animations2();
8145 go_combos();
8146
8147 auto diff = cmd.tile - cmd.copy1;
8148 if(is_undoing)
8149 on_undo.undo();
8150 else if(!handle_combo_move({cmd.tile,cmd.tile+cmd.copycnt-1},{cmd.copy1,cmd.copy1+cmd.copycnt-1}, diff, on_undo))
8151 return false;
8152
8153 for(int32_t t=(cmd.tile<cmd.copy1)?0:(cmd.copycnt-1); (cmd.tile<cmd.copy1)?(t<cmd.copycnt):(t>=0); (cmd.tile<cmd.copy1)?(t++):(t--))
8154 {
8155 if(cmd.tile+t < MAXCOMBOS)
8156 {
8157 combobuf[cmd.tile+t]=combobuf[cmd.copy1+t];
8158 clear_combo(cmd.copy1+t);
8159 }
8160 }
8161
8162 setup_combo_animations();
8163 setup_combo_animations2();
8164 saved=false;
8165 return true;
8166 }
8167
8168 void move_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt)
8169 {
8170 if(tile2<tile)
8171 {
8172 zc_swap(tile,tile2);
8173 }
8174
8175 if(tile==copy)
8176 {
8177 copy=-1;
8178 tile2=tile;
8179 return;
8180 }
8181
8182 combo_move_data cmd;
8183 cmd.tile = tile;
8184 cmd.tile2 = tile2;
8185 cmd.copy1 = copy;
8186 cmd.copycnt = copycnt;
8187
8188 ComboMoveUndo on_undo;
8189 if(!do_movecombo(cmd, on_undo))
8190 return;
8191 last_combo_move_list = std::move(on_undo);
8192 copy=-1;
8193 tile2=tile;
8194 }
8195
8196 void do_delete_tiles(int32_t firsttile, int32_t lasttile, bool rect_sel)
8197 {
8198 if(firsttile > lasttile)
8199 zc_swap(firsttile,lasttile);
8200 int32_t coldiff = 0;
8201 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8202 {
8203 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8204 firsttile-=coldiff;
8205 lasttile+=coldiff;
8206 }
8207 for(int32_t t=firsttile; t<=lasttile; ++t)
8208 if(!rect_sel ||
8209 ((TILECOL(t)>=TILECOL(firsttile)) &&
8210 (TILECOL(t)<=TILECOL(lasttile))))
8211 reset_tile(newtilebuf, t, tf4Bit);
8212 saved=false;
8213 register_blank_tiles();
8214 }
8215
8216 void delete_tiles(int32_t &tile,int32_t &tile2,bool rect_sel)
8217 {
8218 char buf[40];
8219
8220 if(tile==tile2)
8221 {
8222 sprintf(buf,"Delete tile %d?",tile);
8223 }
8224 else
8225 {
8226 sprintf(buf,"Delete tiles %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
8227 }
8228
8229 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8230 {
8231 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8232
8233 go_tiles();
8234
8235 //if copying to an earlier tile, copy from left to right
8236 //otherwise, copy from right to left
8237 do_delete_tiles(firsttile, lasttile, rect_sel);
8238
8239 tile=tile2=zc_min(tile,tile2);
8240 saved=false;
8241 register_blank_tiles();
8242 }
8243 }
8244
8245 void overlay_tile2(int32_t dest,int32_t src,int32_t cs,bool backwards)
8246 {
8247 byte buf[256];
8248 go_tiles();
8249
8250 unpack_tile(newtilebuf, dest, 0, false);
8251
8252 for(int32_t i=0; i<256; i++)
8253 buf[i] = unpackbuf[i];
8254
8255 unpack_tile(newtilebuf, src, 0, false);
8256
8257 if(newtilebuf[src].format>tf4Bit)
8258 {
8259 cs=0;
8260 }
8261
8262 cs &= 15;
8263 cs <<= CSET_SHFT;
8264
8265 for(int32_t i=0; i<256; i++)
8266 {
8267 if(backwards)
8268 {
8269 if(!buf[i])
8270 {
8271 buf[i] = unpackbuf[i]+cs;
8272 }
8273 }
8274 else
8275 {
8276 if(unpackbuf[i])
8277 {
8278 buf[i] = unpackbuf[i]+cs;
8279 }
8280 }
8281 }
8282
8283 pack_tile(newtilebuf, buf,dest);
8284 saved=false;
8285 }
8286
8287 void mass_overlay_tile(int32_t dest1, int32_t dest2, int32_t src, int32_t cs, bool backwards, bool rect_sel)
8288 {
8289 //byte buf[256];
8290 go_tiles();
8291
8292 if(!rect_sel)
8293 {
8294 for(int32_t d=dest1; d <= dest2; ++d)
8295 {
8296 /*unpack_tile(newtilebuf, d, 0, false);
8297
8298 for(int32_t i=0; i<256; i++)
8299 {
8300 if(!backwards)
8301 {
8302 if(!buf[i])
8303 {
8304 buf[i] = unpackbuf[i] + cs;
8305 }
8306 }
8307 else
8308 {
8309 if(unpackbuf[i])
8310 {
8311 buf[i] = unpackbuf[i] + cs;
8312 }
8313 }
8314 }
8315
8316 pack_tile(newtilebuf, buf,d);
8317 */
8318
8319 overlay_tile(newtilebuf,d,src,cs,backwards);
8320
8321 if(!blank_tile_table[src])
8322 {
8323 blank_tile_table[d]=false;
8324 }
8325 }
8326 }
8327 else
8328 {
8329 int32_t rmin=zc_min(TILEROW(dest1),TILEROW(dest2));
8330 int32_t rmax=zc_max(TILEROW(dest1),TILEROW(dest2));
8331 int32_t cmin=zc_min(TILECOL(dest1),TILECOL(dest2));
8332 int32_t cmax=zc_max(TILECOL(dest1),TILECOL(dest2));
8333 int32_t d=0;
8334
8335 for(int32_t j=cmin; j<=cmax; ++j)
8336 {
8337 for(int32_t k=rmin; k<=rmax; ++k)
8338 {
8339 d=j+TILES_PER_ROW*k;
8340 /*unpack_tile(newtilebuf, d, 0, false);
8341
8342 for(int32_t i=0; i<256; i++)
8343 {
8344 if(!backwards)
8345 {
8346 if(!buf[i])
8347 {
8348 buf[i] = unpackbuf[i] + cs;
8349 }
8350 }
8351 else
8352 {
8353 if(unpackbuf[i])
8354 {
8355 buf[i] = unpackbuf[i] + cs;
8356 }
8357 }
8358 }
8359
8360 pack_tile(newtilebuf, buf,d);
8361 */
8362
8363 overlay_tile(newtilebuf,d,src,cs,backwards);
8364
8365 if(!blank_tile_table[src])
8366 {
8367 blank_tile_table[d]=false;
8368 }
8369 }
8370 }
8371 }
8372
8373 return;
8374 }
8375
8376 void sel_tile(int32_t &tile, int32_t &tile2, int32_t &first, int32_t type, int32_t s)
8377 {
8378 tile+=s;
8379 bound(tile,0,NEWMAXTILES-1);
8380
8381 if(type!=0 || !(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
8382 tile2 = tile;
8383
8384 first = tile - (tile%TILES_PER_PAGE);
8385 }
8386
8387 void convert_tile(int32_t t, int32_t bp2, int32_t cs, bool shift, bool alt)
8388 {
8389 int32_t cst;
8390
8391 switch(bp2)
8392 {
8393 case tf4Bit:
8394 switch(newtilebuf[t].format)
8395 {
8396 case tf4Bit:
8397 //already in the right format
8398 break;
8399
8400 case tf8Bit:
8401 unpack_tile(newtilebuf, t, 0, true);
8402
8403 if(alt) //reduce
8404 {
8405 for(int32_t i=0; i<256; i++)
8406 {
8407 if(!shift||unpackbuf[i]!=0)
8408 {
8409 unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
8410 }
8411 }
8412 }
8413 else //truncate
8414 {
8415 for(int32_t i=0; i<256; i++)
8416 {
8417 unpackbuf[i]&=15;
8418 }
8419 }
8420
8421 reset_tile(newtilebuf, t, tf4Bit);
8422 pack_tile(newtilebuf, unpackbuf, t);
8423 break;
8424 }
8425
8426 break;
8427
8428 case tf8Bit:
8429 switch(newtilebuf[t].format)
8430 {
8431 case tf4Bit:
8432 unpack_tile(newtilebuf, t, 0, true);
8433 cst = cs&15;
8434 cst <<= CSET_SHFT;
8435
8436 for(int32_t i=0; i<256; i++)
8437 {
8438 if(!shift||unpackbuf[i]!=0)
8439 {
8440 unpackbuf[i]+=cst;
8441 }
8442 }
8443
8444 reset_tile(newtilebuf, t, tf8Bit);
8445 pack_tile(newtilebuf, unpackbuf, t);
8446 break;
8447
8448 case tf8Bit:
8449 //already in the right format
8450 break;
8451 }
8452
8453 break;
8454 }
8455 }
8456
8457 static DIALOG create_relational_tiles_dlg[] =
8458 {
8459 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
8460 9 { jwin_win_proc, 0, 0, 160, 92, vc(0), vc(11), 0, D_EXIT, 0, 0, (void *) "Tile Setup", NULL, NULL },
8461 9 { jwin_rtext_proc, 74, 28, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Frames:", NULL, NULL },
8462 9 { jwin_edit_proc, 78, 24, 48, 16, 0, 0, 0, 0, 6, 0, NULL, NULL, NULL },
8463 9 { jwin_radio_proc, 8, 44, 64, 9, vc(14), vc(1), 0, D_SELECTED, 0, 0, (void *) "Relational", NULL, NULL },
8464 9 { jwin_radio_proc, 68, 44, 64, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "Dungeon Carving", NULL, NULL },
8465 9 { jwin_button_proc, 10, 66, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
8466 9 { jwin_button_proc, 90, 66, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
8467 9 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
8468 9 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
8469 };
8470
8471 void draw_tile_list_window()
8472 {
8473 int32_t w = 640;
8474 int32_t h = 480;
8475
8476 int32_t window_xofs=(zq_screen_w-w-12)>>1;
8477 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
8478 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
8479 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
8480
8481 FONT *oldfont = font;
8482 font = get_zc_font(font_lfont);
8483 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Tile", true);
8484 font=oldfont;
8485 return;
8486 }
8487
8488 void show_blank_tile(int32_t t)
8489 {
8490 char tbuf[80], tbuf2[80], tbuf3[80];
8491 sprintf(tbuf, "Tile is%s blank.", blank_tile_table[t]?"":" not");
8492 sprintf(tbuf2, "%c %c", blank_tile_quarters_table[t*4]?'X':'-', blank_tile_quarters_table[(t*4)+1]?'X':'-');
8493 sprintf(tbuf3, "%c %c", blank_tile_quarters_table[(t*4)+2]?'X':'-', blank_tile_quarters_table[(t*4)+3]?'X':'-');
8494 jwin_alert("Blank Tile Information",tbuf,tbuf2,tbuf3,"&OK",NULL,13,27,get_zc_font(font_lfont));
8495 }
8496
8497 void do_convert_tile(int32_t tile, int32_t tile2, int32_t cs, bool rect_sel, bool fourbit, bool shift, bool alt)
8498 {
8499 char buf[80];
8500 sprintf(buf, "Do you want to convert the selected %s to %d-bit color?", tile==tile2?"tile":"tiles",fourbit?4:8);
8501
8502 if(jwin_alert("Convert Tile?",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8503 {
8504 go_tiles();
8505 saved=false;
8506
8507 if(fourbit)
8508 {
8509 memset(cset_reduce_table, 0, 256);
8510 memset(col_diff,0,3*128);
8511 calc_cset_reduce_table(RAMpal, cs);
8512 }
8513
8514 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8515
8516 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8517 {
8518 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8519 firsttile-=coldiff;
8520 lasttile+=coldiff;
8521 }
8522
8523 for(int32_t t=firsttile; t<=lasttile; t++)
8524 if(!rect_sel ||
8525 ((TILECOL(t)>=TILECOL(firsttile)) &&
8526 (TILECOL(t)<=TILECOL(lasttile))))
8527 convert_tile(t, fourbit?tf4Bit:tf8Bit, cs, shift, alt);
8528
8529 tile=tile2=zc_min(tile,tile2);
8530 }
8531 }
8532
8533
8534 int32_t readtilefile(PACKFILE *f)
8535 {
8536 dword section_version=0;
8537 dword section_cversion=0;
8538 int32_t zversion = 0;
8539 int32_t zbuild = 0;
8540
8541 if(!p_igetl(&zversion,f))
8542 {
8543 return 0;
8544 }
8545 if(!p_igetl(&zbuild,f))
8546 {
8547 return 0;
8548 }
8549 if(!p_igetw(&section_version,f))
8550 {
8551 return 0;
8552 }
8553 if(!p_igetw(&section_cversion,f))
8554 {
8555 return 0;
8556 }
8557 al_trace("readoneweapon section_version: %d\n", section_version);
8558 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8559
8560 if ( zversion > ZELDA_VERSION )
8561 {
8562 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8563 return 0;
8564 }
8565
8566 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8567 {
8568 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8569 return 0;
8570
8571 }
8572 else
8573 {
8574 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8575 }
8576
8577 int32_t index = 0;
8578 int32_t count = 0;
8579
8580 //tile id
8581 if(!p_igetl(&index,f))
8582 {
8583 return 0;
8584 }
8585 al_trace("Reading tile: index(%d)\n", index);
8586
8587 //tile count
8588 if(!p_igetl(&count,f))
8589 {
8590 return 0;
8591 }
8592 al_trace("Reading tile: count(%d)\n", count);
8593
8594
8595
8596
8597 for ( int32_t tilect = 0; tilect < count; tilect++ )
8598 {
8599 byte *temp_tile = new byte[tilesize(tf32Bit)];
8600 byte format=tf4Bit;
8601 memset(temp_tile, 0, tilesize(tf32Bit));
8602 if(!p_getc(&format,f))
8603 {
8604 delete[] temp_tile;
8605 return 0;
8606 }
8607
8608
8609 if(!pfread(temp_tile,tilesize(format),f))
8610 {
8611 delete[] temp_tile;
8612 return 0;
8613 }
8614
8615 reset_tile(newtilebuf, index+(tilect), format);
8616 memcpy(newtilebuf[index+(tilect)].data,temp_tile,tilesize(newtilebuf[index+(tilect)].format));
8617 delete[] temp_tile;
8618 }
8619
8620
8621 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8622
8623 register_blank_tiles();
8624 register_used_tiles();
8625
8626 return 1;
8627
8628 }
8629
8630 int32_t readtilefile_to_location(PACKFILE *f, int32_t start, int32_t skip)
8631 {
8632 dword section_version=0;
8633 dword section_cversion=0;
8634 int32_t zversion = 0;
8635 int32_t zbuild = 0;
8636
8637 if(!p_igetl(&zversion,f))
8638 {
8639 return 0;
8640 }
8641 if(!p_igetl(&zbuild,f))
8642 {
8643 return 0;
8644 }
8645 if(!p_igetw(&section_version,f))
8646 {
8647 return 0;
8648 }
8649 if(!p_igetw(&section_cversion,f))
8650 {
8651 return 0;
8652 }
8653 al_trace("readoneweapon section_version: %d\n", section_version);
8654 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8655
8656 if ( zversion > ZELDA_VERSION )
8657 {
8658 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8659 return 0;
8660 }
8661
8662 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8663 {
8664 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8665 return 0;
8666
8667 }
8668 else
8669 {
8670 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8671 }
8672
8673 int32_t index = 0;
8674 int32_t count = 0;
8675
8676 //tile id
8677 if(!p_igetl(&index,f))
8678 {
8679 return 0;
8680 }
8681 al_trace("Reading tile: index(%d)\n", index);
8682
8683 //tile count
8684 if(!p_igetl(&count,f))
8685 {
8686 return 0;
8687 }
8688 al_trace("Reading tile: count(%d)\n", count);
8689
8690
8691 for ( int32_t tilect = 0; tilect < count; tilect++ )
8692 {
8693 byte *temp_tile = new byte[tilesize(tf32Bit)];
8694 byte format=tf4Bit;
8695 memset(temp_tile, 0, tilesize(tf32Bit));
8696 if(!p_getc(&format,f))
8697 {
8698 delete[] temp_tile;
8699 return 0;
8700 }
8701
8702
8703 if(!pfread(temp_tile,tilesize(format),f))
8704 {
8705 delete[] temp_tile;
8706 return 0;
8707 }
8708
8709 reset_tile(newtilebuf, start+(tilect), format);
8710 if ( skip )
8711 {
8712 if ( (start+(tilect)) < skip )
8713 {
8714 delete[] temp_tile;
8715 continue;
8716 }
8717
8718 }
8719 if ( start+(tilect) < NEWMAXTILES )
8720 {
8721 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8722 }
8723 delete[] temp_tile;
8724
8725 }
8726
8727
8728 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8729
8730 register_blank_tiles();
8731 register_used_tiles();
8732
8733 return 1;
8734
8735 }
8736
8737
8738 int32_t readtilefile_to_location(PACKFILE *f, int32_t start)
8739 {
8740 dword section_version=0;
8741 dword section_cversion=0;
8742 int32_t zversion = 0;
8743 int32_t zbuild = 0;
8744
8745 if(!p_igetl(&zversion,f))
8746 {
8747 return 0;
8748 }
8749 if(!p_igetl(&zbuild,f))
8750 {
8751 return 0;
8752 }
8753 if(!p_igetw(&section_version,f))
8754 {
8755 return 0;
8756 }
8757 if(!p_igetw(&section_cversion,f))
8758 {
8759 return 0;
8760 }
8761 al_trace("readoneweapon section_version: %d\n", section_version);
8762 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8763
8764 if ( zversion > ZELDA_VERSION )
8765 {
8766 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8767 return 0;
8768 }
8769
8770 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8771 {
8772 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8773 return 0;
8774
8775 }
8776 else
8777 {
8778 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8779 }
8780
8781 int32_t index = 0;
8782 int32_t count = 0;
8783
8784 //tile id
8785 if(!p_igetl(&index,f))
8786 {
8787 return 0;
8788 }
8789 al_trace("Reading tile: index(%d)\n", index);
8790
8791 //tile count
8792 if(!p_igetl(&count,f))
8793 {
8794 return 0;
8795 }
8796 al_trace("Reading tile: count(%d)\n", count);
8797
8798
8799
8800
8801 for ( int32_t tilect = 0; tilect < count; tilect++ )
8802 {
8803 byte *temp_tile = new byte[tilesize(tf32Bit)];
8804 byte format=tf4Bit;
8805 memset(temp_tile, 0, tilesize(tf32Bit));
8806
8807 if(!p_getc(&format,f))
8808 {
8809 delete[] temp_tile;
8810 return 0;
8811 }
8812
8813
8814 if(!pfread(temp_tile,tilesize(format),f))
8815 {
8816 delete[] temp_tile;
8817 return 0;
8818 }
8819
8820 reset_tile(newtilebuf, start+(tilect), format);
8821 if ( start+(tilect) < NEWMAXTILES )
8822 {
8823 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8824 }
8825 delete[] temp_tile;
8826 }
8827
8828
8829 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8830
8831 register_blank_tiles();
8832 register_used_tiles();
8833
8834 return 1;
8835
8836 }
8837 int32_t writetilefile(PACKFILE *f, int32_t index, int32_t count)
8838 {
8839 dword section_version=V_TILES;
8840 dword section_cversion=CV_TILES;
8841 int32_t zversion = ZELDA_VERSION;
8842 int32_t zbuild = VERSION_BUILD;
8843
8844 if(!p_iputl(zversion,f))
8845 {
8846 return 0;
8847 }
8848 if(!p_iputl(zbuild,f))
8849 {
8850 return 0;
8851 }
8852 if(!p_iputw(section_version,f))
8853 {
8854 return 0;
8855 }
8856
8857 if(!p_iputw(section_cversion,f))
8858 {
8859 return 0;
8860 }
8861
8862 //start tile id
8863 if(!p_iputl(index,f))
8864 {
8865 return 0;
8866 }
8867
8868 //count
8869 if(!p_iputl(count,f))
8870 {
8871 return 0;
8872 }
8873
8874 for ( int32_t tilect = 0; tilect < count; tilect++ )
8875 {
8876 //al_trace("Tile id: %d\n",index+(tilect));
8877 if(!p_putc(newtilebuf[index+(tilect)].format,f))
8878 {
8879 return 0;
8880 }
8881 //al_trace("Tile format: %d\n", newtilebuf[index+(tilect)].format);
8882 if(!pfwrite(newtilebuf[index+(tilect)].data,tilesize(newtilebuf[index+(tilect)].format),f))
8883 {
8884 return 0;
8885 }
8886 }
8887
8888 return 1;
8889
8890 }
8891
8892 static int32_t _selected_tile=-1, _selected_tcset=-1;
8893 int32_t select_tile(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
8894 {
8895 popup_zqdialog_start();
8896 reset_combo_animations();
8897 reset_combo_animations2();
8898 bound(tile,0,NEWMAXTILES-1);
8899 ex=exnow;
8900 int32_t done=0;
8901 int32_t oflip=flip;
8902 int32_t otile=tile;
8903 int32_t ocs=cs;
8904 int32_t first=(tile/TILES_PER_PAGE)*TILES_PER_PAGE; //first tile on the current page
8905 int32_t copy=-1;
8906 int32_t tile2=tile,copycnt=0;
8907 int32_t tile_clicked=-1;
8908 bool rect_sel=true;
8909 bound(first,0,(TILES_PER_PAGE*TILE_PAGES)-1);
8910 position_mouse_z(0);
8911
8912 go();
8913
8914 register_used_tiles();
8915 int32_t w = 640;
8916 int32_t h = 480;
8917 int32_t window_xofs=(zq_screen_w-w-12)>>1;
8918 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
8919 int32_t screen_xofs=window_xofs+6;
8920 int32_t screen_yofs=window_yofs+25;
8921 int32_t panel_yofs=3;
8922 int32_t mul = 2;
8923 FONT *tfont = get_zc_font(font_lfont_l);
8924
8925 draw_tile_list_window();
8926 int32_t f=0;
8927 draw_tiles(first,cs,f);
8928
8929 if(type==0)
8930 {
8931 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
8932 }
8933 else
8934 {
8935 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
8936 }
8937
8938 go_tiles();
8939
8940 while(gui_mouse_b())
8941 {
8942 /* do nothing */
8943 rest(1);
8944 }
8945
8946 bool bdown=false;
8947
8948 #define FOREACH_START(_t) \
8949 { \
8950 int32_t _first, _last; \
8951 if(is_rect) \
8952 { \
8953 _first=top*TILES_PER_ROW+left; \
8954 _last=_first+rows*TILES_PER_ROW|+columns-1; \
8955 } \
8956 else \
8957 { \
8958 _first=zc_min(tile, tile2); \
8959 _last=zc_max(tile, tile2); \
8960 } \
8961 for(int32_t _t=_first; _t<=_last; _t++) \
8962 { \
8963 if(is_rect) \
8964 { \
8965 int32_t row=TILEROW(_t); \
8966 if(row<top || row>=top+rows) \
8967 continue; \
8968 int32_t col=TILECOL(_t); \
8969 if(col<left || col>=left+columns) \
8970 continue; \
8971 } \
8972
8973 #define FOREACH_END\
8974 } \
8975 }
8976
8977 bool did_snap = false;
8978 int otl = tile, otl2 = tile2;
8979 do
8980 {
8981 HANDLE_CLOSE_ZQDLG();
8982 if(exiting_program) break;
8983 rest(4);
8984 int32_t top=TILEROW(zc_min(tile, tile2));
8985 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
8986 int32_t rows=TILEROW(zc_max(tile, tile2))-top+1;
8987 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
8988 bool is_rect=(rows==1)||(columns==TILES_PER_ROW)||rect_sel;
8989 bool redraw=false;
8990
8991 if(mouse_z!=0)
8992 {
8993 sel_tile(tile,tile2,first,type,((mouse_z/abs(mouse_z))*(-1)*TILES_PER_PAGE));
8994 position_mouse_z(0);
8995 redraw=true;
8996 }
8997
8998 if(keypressed())
8999 {
9000 switch(readkey()>>8)
9001 {
9002 case KEY_ENTER_PAD:
9003 case KEY_ENTER:
9004 done=2;
9005 break;
9006
9007 case KEY_ESC:
9008 done=1;
9009 break;
9010
9011 case KEY_F1:
9012 onHelp();
9013 break;
9014
9015 case KEY_EQUALS:
9016 case KEY_PLUS_PAD:
9017 {
9018 if(CHECK_CTRL_CMD ||
9019 key[KEY_ALT] || key[KEY_ALTGR])
9020 {
9021 FOREACH_START(t)
9022 if(key[KEY_ALT] || key[KEY_ALTGR])
9023 shift_tile_colors(t, 16, false);
9024 else
9025 shift_tile_colors(t, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9026 FOREACH_END
9027
9028 register_blank_tiles();
9029 }
9030 else if(edit_cs)
9031 cs = (cs<13) ? cs+1:0;
9032
9033 redraw=true;
9034 break;
9035 }
9036
9037 case KEY_Z:
9038 case KEY_F12:
9039 {
9040 if(!did_snap)
9041 {
9042 //Export tile page as screenshot
9043 PALETTE temppal;
9044 get_palette(temppal);
9045 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
9046 draw_tiles(tempbmp,first,cs,f,false,true);
9047 save_bitmap(getSnapName(), tempbmp, RAMpal);
9048 destroy_bitmap(tempbmp);
9049
9050 redraw = true;
9051 did_snap = true;
9052 }
9053 break;
9054 }
9055
9056 case KEY_S:
9057 {
9058 if(!getname("Save ZTILE(.ztile)", "ztile", NULL,datapath,false))
9059 break;
9060 PACKFILE *f=pack_fopen_password(temppath,F_WRITE, "");
9061 if(!f) break;
9062 al_trace("Saving tile: %d\n", tile);
9063 writetilefile(f,tile,1);
9064 pack_fclose(f);
9065 break;
9066 }
9067 case KEY_L:
9068 {
9069 if(!getname("Load ZTILE(.ztile)", "ztile", NULL,datapath,false))
9070 break;
9071 PACKFILE *f=pack_fopen_password(temppath,F_READ, "");
9072 if(!f) break;
9073 al_trace("Saving tile: %d\n", tile);
9074 if (!readtilefile(f))
9075 {
9076 al_trace("Could not read from .ztile packfile %s\n", temppath);
9077 jwin_alert("ZTILE File: Error","Could not load the specified Tile.",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9078 }
9079 else
9080 {
9081 jwin_alert("ZTILE File: Success!","Loaded the source tiles to your tile sheets!",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9082 }
9083
9084 pack_fclose(f);
9085 //register_blank_tiles();
9086 //register_used_tiles();
9087 redraw=true;
9088 break;
9089 }
9090 case KEY_MINUS:
9091 case KEY_MINUS_PAD:
9092 {
9093 if(CHECK_CTRL_CMD ||
9094 key[KEY_ALT] || key[KEY_ALTGR])
9095 {
9096 FOREACH_START(t)
9097 if(key[KEY_ALT] || key[KEY_ALTGR])
9098 shift_tile_colors(t, -16, false);
9099 else
9100 shift_tile_colors(t, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9101 FOREACH_END
9102
9103 register_blank_tiles();
9104 }
9105 else if(edit_cs)
9106 cs = (cs>0) ? cs-1:13;
9107
9108 redraw=true;
9109 break;
9110 }
9111
9112 case KEY_UP:
9113 {
9114 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9115 {
9116 case 3: //ALT and CTRL
9117 case 2: //ALT
9118 if(is_rect)
9119 {
9120 saved=false;
9121 go_slide_tiles(columns, rows, top, left);
9122 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9123 bool same = true;
9124
9125 for(int32_t d=0; d<columns; d++)
9126 {
9127 for(int32_t s=0; s<rows; s++)
9128 {
9129 int32_t t=((top+s)*TILES_PER_ROW)+left+d;
9130
9131 if(newtilebuf[t].format!=bitcheck) same = false;
9132 }
9133 }
9134
9135 if(!same) break;
9136
9137 // This used to do something. Too lazy to remove.
9138 // Can probably remove the above "same" check too.
9139 bitcheck = 2;
9140
9141 for(int32_t c=0; c<columns; c++)
9142 {
9143 for(int32_t r=0; r<rows; r++)
9144 {
9145 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9146 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(8*bitcheck));
9147 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data);
9148
9149 for(int32_t pixelrow=0; pixelrow<16*bitcheck; pixelrow++)
9150 {
9151 if(pixelrow==15*bitcheck)
9152 {
9153 int32_t srctile=temptile+TILES_PER_ROW;
9154 if(srctile>=NEWMAXTILES)
9155 srctile-=rows*TILES_PER_ROW;
9156 src_pixelrow=(qword*)(newtilebuf[srctile].data);
9157 }
9158
9159 *dest_pixelrow=*src_pixelrow;
9160 dest_pixelrow++;
9161 src_pixelrow++;
9162 }
9163 }
9164
9165 qword *dest_pixelrow=(qword*)(newtilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9166
9167 for(int32_t b=0; b<bitcheck; b++,dest_pixelrow++)
9168 {
9169 if((CHECK_CTRL_CMD))
9170 {
9171 *dest_pixelrow=0;
9172 }
9173 else
9174 {
9175 qword *src_pixelrow=(qword*)(newundotilebuf[(top*TILES_PER_ROW)+left+c].data+(8*b));
9176 *dest_pixelrow=*src_pixelrow;
9177 }
9178 }
9179 }
9180 }
9181
9182 register_blank_tiles();
9183 redraw=true;
9184 break;
9185
9186 case 1: //CTRL
9187 case 0: //None
9188 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(tile_page_row(tile)*TILES_PER_ROW):-TILES_PER_ROW);
9189 redraw=true;
9190
9191 default: //Others
9192 break;
9193 }
9194 }
9195 break;
9196
9197 case KEY_DOWN:
9198 {
9199 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9200 {
9201 case 3: //ALT and CTRL
9202 case 2: //ALT
9203 if(is_rect)
9204 {
9205 saved=false;
9206 go_slide_tiles(columns, rows, top, left);
9207 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9208 bool same = true;
9209
9210 for(int32_t c=0; c<columns; c++)
9211 {
9212 for(int32_t r=0; r<rows; r++)
9213 {
9214 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9215
9216 if(newtilebuf[t].format!=bitcheck) same = false;
9217 }
9218 }
9219
9220 if(!same) break;
9221
9222 // This used to do something. Too lazy to remove.
9223 // Can probably remove the above "same" check too.
9224 bitcheck = 2;
9225
9226 for(int32_t c=0; c<columns; c++)
9227 {
9228 for(int32_t r=rows-1; r>=0; r--)
9229 {
9230 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9231 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(112*bitcheck)+(8*(bitcheck-1)));
9232 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data+(120*bitcheck)+(8*(bitcheck-1)));
9233
9234 for(int32_t pixelrow=(8<<bitcheck)-1; pixelrow>=0; pixelrow--)
9235 {
9236 if(pixelrow<bitcheck)
9237 {
9238 int32_t srctile=temptile-TILES_PER_ROW;
9239 if(srctile<0)
9240 srctile+=rows*TILES_PER_ROW;
9241 qword *tempsrc=(qword*)(newtilebuf[srctile].data+(120*bitcheck)+(8*pixelrow));
9242 *dest_pixelrow=*tempsrc;
9243 //*dest_pixelrow=0;
9244 }
9245 else
9246 {
9247 *dest_pixelrow=*src_pixelrow;
9248 }
9249
9250 dest_pixelrow--;
9251 src_pixelrow--;
9252 }
9253 }
9254
9255 qword *dest_pixelrow=(qword*)(newtilebuf[(top*TILES_PER_ROW)+left+c].data);
9256 qword *src_pixelrow=(qword*)(newundotilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9257
9258 for(int32_t b=0; b<bitcheck; b++)
9259 {
9260 if((CHECK_CTRL_CMD))
9261 {
9262 *dest_pixelrow=0;
9263 }
9264 else
9265 {
9266 *dest_pixelrow=*src_pixelrow;
9267 }
9268
9269 dest_pixelrow++;
9270 src_pixelrow++;
9271 }
9272 }
9273 }
9274
9275 register_blank_tiles();
9276 redraw=true;
9277 break;
9278
9279 case 1: //CTRL
9280 case 0: //None
9281 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_ROWS_PER_PAGE-1)-tile_page_row(tile))*TILES_PER_ROW:TILES_PER_ROW);
9282 redraw=true;
9283
9284 default: //Others
9285 break;
9286 }
9287 }
9288 break;
9289
9290 case KEY_LEFT:
9291 {
9292 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9293 {
9294 case 3: //ALT and CTRL
9295 case 2: //ALT
9296 if(is_rect)
9297 {
9298 saved=false;
9299 go_slide_tiles(columns, rows, top, left);
9300 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9301 bool same = true;
9302
9303 for(int32_t c=0; c<columns; c++)
9304 {
9305 for(int32_t r=0; r<rows; r++)
9306 {
9307 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9308
9309 if(newtilebuf[t].format!=bitcheck) same = false;
9310 }
9311 }
9312
9313 if(!same) break;
9314
9315 // This used to do something. Too lazy to remove.
9316 // Can probably remove the above "same" check too.
9317 bitcheck = 2;
9318
9319 for(int32_t r=0; r<rows; r++)
9320 {
9321 for(int32_t c=0; c<columns; c++)
9322 {
9323 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9324 byte *dest_pixelrow=(newtilebuf[temptile].data);
9325
9326 for(int32_t pixelrow=0; pixelrow<16; pixelrow++)
9327 {
9328 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9329 {
9330 *dest_pixelrow=*(dest_pixelrow+1);
9331 dest_pixelrow++;
9332 }
9333
9334 if(c==columns-1)
9335 {
9336 if(!(CHECK_CTRL_CMD))
9337 {
9338 byte *tempsrc=(newundotilebuf[((top+r)*TILES_PER_ROW)+left].data+(pixelrow*8*bitcheck));
9339 *dest_pixelrow=*tempsrc;
9340 }
9341 }
9342 else
9343
9344 {
9345 byte *tempsrc=(newtilebuf[temptile+1].data+(pixelrow*8*bitcheck));
9346 *dest_pixelrow=*tempsrc;
9347 }
9348
9349 dest_pixelrow++;
9350 }
9351 }
9352 }
9353
9354 register_blank_tiles();
9355 redraw=true;
9356 }
9357
9358 break;
9359
9360 case 1: //CTRL
9361 case 0: //None
9362 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile%TILES_PER_ROW):-1);
9363 redraw=true;
9364
9365 default: //Others
9366 break;
9367 }
9368 }
9369 break;
9370
9371 case KEY_RIGHT:
9372 {
9373 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9374 {
9375 case 3: //ALT and CTRL
9376 case 2: //ALT
9377 if(is_rect)
9378 {
9379 saved=false;
9380 go_slide_tiles(columns, rows, top, left);
9381 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9382 bool same = true;
9383
9384 for(int32_t c=0; c<columns; c++)
9385 {
9386 for(int32_t r=0; r<rows; r++)
9387 {
9388 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9389
9390 if(newtilebuf[t].format!=bitcheck) same = false;
9391 }
9392 }
9393
9394 if(!same) break;
9395
9396 // This used to do something. Too lazy to remove.
9397 // Can probably remove the above "same" check too.
9398 bitcheck = 2;
9399
9400 for(int32_t r=0; r<rows; r++)
9401 {
9402 for(int32_t c=columns-1; c>=0; c--)
9403 {
9404 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9405 byte *dest_pixelrow=(newtilebuf[temptile].data)+(128*bitcheck)-1;
9406
9407 for(int32_t pixelrow=15; pixelrow>=0; pixelrow--)
9408 {
9409 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9410 {
9411 *dest_pixelrow=*(dest_pixelrow-1);
9412 dest_pixelrow--;
9413 }
9414
9415 if(c==0)
9416 {
9417 if(!(CHECK_CTRL_CMD))
9418 {
9419 byte *tempsrc=(newundotilebuf[(((top+r)*TILES_PER_ROW)+left+columns-1)].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9420 *dest_pixelrow=*tempsrc;
9421 }
9422 }
9423 else
9424 {
9425 byte *tempsrc=(newtilebuf[temptile-1].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9426 *dest_pixelrow=*tempsrc;
9427 }
9428
9429 dest_pixelrow--;
9430 }
9431 }
9432 }
9433
9434 register_blank_tiles();
9435 redraw=true;
9436 }
9437
9438 break;
9439
9440 case 1: //CTRL
9441 case 0: //None
9442 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILES_PER_ROW)-(tile%TILES_PER_ROW)-1:1);
9443 redraw=true;
9444
9445 default: //Others
9446 break;
9447 }
9448 }
9449 break;
9450
9451 case KEY_PGUP:
9452 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(TILEROW(tile)*TILES_PER_ROW):-TILES_PER_PAGE);
9453 redraw=true;
9454 break;
9455
9456 case KEY_PGDN:
9457 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_PAGES*TILE_ROWS_PER_PAGE)-TILEROW(tile)-1)*TILES_PER_ROW:TILES_PER_PAGE);
9458 redraw=true;
9459 break;
9460
9461 case KEY_HOME:
9462 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile):-(tile%TILES_PER_PAGE));
9463 redraw=true;
9464 break;
9465
9466 case KEY_END:
9467 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILE_PAGES)*(TILES_PER_PAGE)-tile-1:(TILES_PER_PAGE)-(tile%TILES_PER_PAGE)-1);
9468 redraw=true;
9469 break;
9470
9471 case KEY_P:
9472 {
9473 int32_t whatPage = gettilepagenumber("Goto Page", (PreFillTileEditorPage?(first/TILES_PER_PAGE):0));
9474
9475 if(whatPage >= 0)
9476 sel_tile(tile,tile2,first,type,((whatPage-TILEPAGE(tile))*TILE_ROWS_PER_PAGE)*TILES_PER_ROW);
9477
9478 break;
9479 }
9480
9481 case KEY_O:
9482 if(type==0 && copy>=0)
9483 {
9484 go_tiles();
9485
9486 if(key[KEY_LSHIFT] ||key[KEY_RSHIFT])
9487 {
9488 mass_overlay_tile(zc_min(tile,tile2),zc_max(tile,tile2),copy,cs,(CHECK_CTRL_CMD), rect_sel);
9489 saved=false;
9490 }
9491 else
9492 {
9493 saved = !overlay_tiles(tile,tile2,copy,copycnt,rect_sel,false,cs,(CHECK_CTRL_CMD));
9494 //overlay_tile(newtilebuf,tile,copy,cs,(CHECK_CTRL_CMD));
9495 }
9496
9497 saved=false;
9498 redraw=true;
9499 }
9500
9501 break;
9502
9503 case KEY_E:
9504 if(type==0)
9505 {
9506 edit_tile(tile,flip,cs);
9507 draw_tile_list_window();
9508 redraw=true;
9509 }
9510
9511 break;
9512
9513 case KEY_G:
9514 if(type==0)
9515 {
9516 grab_tile(tile,cs);
9517 draw_tile_list_window();
9518 redraw=true;
9519 }
9520
9521 break;
9522
9523 case KEY_C:
9524 copy=zc_min(tile,tile2);
9525 copycnt=abs(tile-tile2)+1;
9526 redraw=true;
9527 break;
9528
9529 case KEY_X:
9530 if(type==2)
9531 {
9532 ex=(ex+1)%3;
9533 }
9534
9535 break;
9536
9537 //usetiles=true;
9538 case KEY_R:
9539 if(type==2)
9540 break;
9541 if(type==1)
9542 {
9543 flip = rotate_value(flip);
9544 redraw=true;
9545 break;
9546 }
9547
9548 go_tiles();
9549
9550 if(CHECK_CTRL_CMD)
9551 {
9552 bool go=false;
9553 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
9554 go=true;
9555 else if(massRecolorSetup(cs))
9556 go=true;
9557
9558 if(go)
9559 {
9560 FOREACH_START(t)
9561 massRecolorApply(t);
9562 FOREACH_END
9563
9564 register_blank_tiles();
9565 }
9566 }
9567 else
9568 {
9569 FOREACH_START(t)
9570 rotate_tile(t,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
9571 FOREACH_END
9572 }
9573
9574 redraw=true;
9575 saved=false;
9576 break;
9577
9578 case KEY_SPACE:
9579 rect_sel=!rect_sel;
9580 copy=-1;
9581 redraw=true;
9582 break;
9583
9584 // case KEY_N: go_tiles(); normalize(tile,tile2,flip); flip=0; redraw=true; saved=false; usetiles=true; break;
9585 case KEY_H:
9586 flip^=1;
9587 go_tiles();
9588
9589 if(type==0)
9590 {
9591 normalize(tile,tile2,rect_sel,flip);
9592 flip=0;
9593 }
9594
9595 redraw=true;
9596 break;
9597
9598
9599 case KEY_V:
9600 if(copy==-1)
9601 {
9602 if(type!=2)
9603 {
9604 flip^=2;
9605 go_tiles();
9606
9607 if(type==0)
9608 {
9609 normalize(tile,tile2,rect_sel,flip);
9610 flip=0;
9611 }
9612 }
9613 }
9614 else
9615 {
9616 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9617 go_tiles();
9618 saved = !copy_tiles(tile,tile2,copy,copycnt,rect_sel,false);
9619 }
9620
9621 redraw=true;
9622 break;
9623
9624 case KEY_F:
9625 if(copy==-1)
9626 {
9627 break;
9628 }
9629 else
9630 {
9631 go_tiles();
9632 {
9633 saved = !copy_tiles_floodfill(tile,tile2,copy,copycnt,rect_sel,false);
9634 }
9635 }
9636
9637 redraw=true;
9638 break;
9639
9640 case KEY_DEL:
9641 if(type==0 && (key[KEY_LSHIFT]||key[KEY_RSHIFT]))
9642 {
9643 bool warn = (rect_sel
9644 && ((tile/20)!=(tile2/20))
9645 && !(tile%20==0&&tile2%20==19));
9646 int32_t z=zc_min(tile,tile2);
9647 int32_t count = abs(tile-tile2) + 1;
9648 tile=z;
9649 tile2=NEWMAXTILES;
9650 copy = tile + count;
9651 copycnt = NEWMAXTILES-copy;
9652 char buf[64];
9653
9654 if(count>1)
9655 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9656 else
9657 sprintf(buf,"Remove tile %d?",tile);
9658
9659 AlertDialog("Remove Tiles", std::string(buf)
9660 +"\nThis will offset the tiles that follow!"
9661 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9662 [&](bool ret,bool)
9663 {
9664 if(ret)
9665 {
9666 go_tiles();
9667 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9668 {
9669 redraw=true;
9670 saved=false;
9671 }
9672 }
9673 }).show();
9674 }
9675 delete_tiles(tile,tile2,rect_sel);
9676 redraw=true;
9677 break;
9678
9679 case KEY_U:
9680 {
9681 if(CHECK_CTRL_CMD)
9682 {
9683 //Only toggle the first 2 bits!
9684 show_only_unused_tiles = (show_only_unused_tiles&~3) | (((show_only_unused_tiles&3)+1)%4);
9685 }
9686 else
9687 {
9688 comeback_tiles();
9689 }
9690
9691 redraw=true;
9692 }
9693 break;
9694
9695 case KEY_8:
9696 case KEY_8_PAD:
9697 hide_8bit_marker();
9698 break;
9699
9700 case KEY_I: //insert tiles
9701 if(type==0)
9702 {
9703 bool warn = (rect_sel
9704 && ((tile/20)!=(tile2/20))
9705 && !(tile%20==0&&tile2%20==19));
9706 int32_t z=zc_min(tile,tile2);
9707 int32_t count = abs(tile-tile2) + 1;
9708 tile=z;
9709 tile2=NEWMAXTILES;
9710 copy = tile + count;
9711 copycnt = NEWMAXTILES-copy;
9712
9713 if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) //Remove
9714 {
9715 char buf[64];
9716
9717 if(count>1)
9718 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9719 else
9720 sprintf(buf,"Remove tile %d?",tile);
9721
9722 AlertDialog("Remove Tiles", std::string(buf)
9723 +"\nThis will offset the tiles that follow!"
9724 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9725 [&](bool ret,bool)
9726 {
9727 if(ret)
9728 {
9729 go_tiles();
9730 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9731 {
9732 redraw=true;
9733 saved=false;
9734 }
9735 }
9736 }).show();
9737 }
9738 else
9739 {
9740 char buf[64];
9741
9742 if(count>1)
9743 sprintf(buf,"Insert %d blank tiles?",count);
9744 else
9745 sprintf(buf,"Insert a blank tile?");
9746
9747 AlertDialog("Insert Tiles", std::string(buf)
9748 +"\nThis will offset the tiles that follow!"
9749 +(warn?"\nInserting tiles ignores rectangular selections!":""),
9750 [&](bool ret,bool)
9751 {
9752 if(ret)
9753 {
9754 go_tiles();
9755 if(copy_tiles(copy,tile2,tile,copycnt,false,true))
9756 {
9757 redraw=true;
9758 saved=false;
9759 }
9760 }
9761 }).show();
9762 }
9763
9764 copy=-1;
9765 tile2=tile=z;
9766 }
9767 break;
9768 case KEY_M:
9769 if(type==0)
9770 {
9771 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
9772 {
9773 go_tiles();
9774 if(copy_tiles(tile,tile2,copy,copycnt,rect_sel,true))
9775 saved=false;
9776 }
9777 else if(copy==-1)
9778 {
9779 // I don't know what this was supposed to be doing before.
9780 // It didn't work in anything like a sensible way.
9781 if(rect_sel)
9782 {
9783 make_combos_rect(top, left, rows, columns, cs);
9784 }
9785 else
9786 {
9787 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
9788 }
9789 }
9790
9791 redraw=true;
9792 }
9793 break;
9794
9795 case KEY_D:
9796 {
9797 int32_t frames=1;
9798 char buf[80];
9799 sprintf(buf, "%d", frames);
9800 create_relational_tiles_dlg[0].dp2=get_zc_font(font_lfont);
9801 create_relational_tiles_dlg[2].dp=buf;
9802
9803 large_dialog(create_relational_tiles_dlg);
9804
9805 int32_t ret=do_zqdialog(create_relational_tiles_dlg,2);
9806
9807 if(ret==5)
9808 {
9809 frames=zc_max(atoi(buf),1);
9810 bool same = true;
9811 int32_t bitcheck=newtilebuf[tile].format;
9812
9813 for(int32_t t=1; t<frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); ++t)
9814 {
9815 if(newtilebuf[tile+t].format!=bitcheck) same = false;
9816 }
9817
9818 if(!same)
9819 {
9820 jwin_alert("Error","The source tiles are not","in the same format.",NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9821 break;
9822 }
9823
9824 if(tile+(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96))>NEWMAXTILES)
9825 {
9826 jwin_alert("Error","Too many tiles will be created",NULL,NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9827 break;
9828 }
9829
9830 for(int32_t i=frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); i<(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96)); ++i)
9831 {
9832 reset_tile(newtilebuf, tile+i, bitcheck);
9833 }
9834
9835 if(create_relational_tiles_dlg[3].flags&D_SELECTED)
9836 {
9837 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9838 {
9839 for(int32_t j=0; j<frames; ++j)
9840 {
9841 merge_tiles(tile+(i*frames)+j, (tile+(relational_template[i][0]*frames)+j)<<2, ((tile+(relational_template[i][1]*frames)+j)<<2)+1, ((tile+(relational_template[i][2]*frames)+j)<<2)+2, ((tile+(relational_template[i][3]*frames)+j)<<2)+3);
9842 }
9843 }
9844 }
9845 else
9846 {
9847 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9848 {
9849 for(int32_t j=0; j<frames; ++j)
9850 {
9851 merge_tiles(tile+(i*frames)+j, (tile+(dungeon_carving_template[i][0]*frames)+j)<<2, ((tile+(dungeon_carving_template[i][1]*frames)+j)<<2)+1, ((tile+(dungeon_carving_template[i][2]*frames)+j)<<2)+2, ((tile+(dungeon_carving_template[i][3]*frames)+j)<<2)+3);
9852 }
9853 }
9854 }
9855 }
9856 register_blank_tiles();
9857 register_used_tiles();
9858 redraw=true;
9859 saved=false;
9860 break;
9861 }
9862
9863 case KEY_B:
9864 {
9865 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9866 bool control=(CHECK_CTRL_CMD);
9867 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9868
9869 do_convert_tile(tile, tile2, cs, rect_sel, control, shift, alt);
9870 register_blank_tiles();
9871 }
9872 break;
9873 }
9874
9875 clear_keybuf();
9876 }
9877
9878 if(!(key[KEY_Z] || key[KEY_F12]))
9879 did_snap = false;
9880
9881 if(gui_mouse_b()&1)
9882 {
9883 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
9884 {
9885 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
9886 {
9887 done=1;
9888 }
9889 }
9890
9891 int32_t x=gui_mouse_x()-screen_xofs;
9892 int32_t y=gui_mouse_y()-screen_yofs;
9893
9894 if(y>=0 && y<208*mul)
9895 {
9896 x=zc_min(zc_max(x,0),(320*mul)-1);
9897 int32_t t = (y>>(5))*TILES_PER_ROW + (x>>(5)) + first;
9898
9899 if(type==0 && (key[KEY_LSHIFT] || key[KEY_RSHIFT]))
9900 {
9901 tile2=t;
9902 }
9903 else
9904 {
9905 tile=tile2=t;
9906 }
9907
9908 if(tile_clicked!=t)
9909 {
9910 dclick_status=DCLICK_NOT;
9911 }
9912 else if(dclick_status == DCLICK_AGAIN)
9913 {
9914 while(gui_mouse_b())
9915 {
9916 /* do nothing */
9917 rest(1);
9918 }
9919
9920 if(((y>>(5))*TILES_PER_ROW + (x>>(5)) + first)!=t)
9921 {
9922 dclick_status=DCLICK_NOT;
9923 }
9924 else
9925 {
9926 if(type==0)
9927 {
9928 edit_tile(tile,flip,cs);
9929 draw_tile_list_window();
9930 redraw=true;
9931 }
9932 else
9933 {
9934 done=2;
9935 }
9936 }
9937 }
9938
9939 tile_clicked=t;
9940 }
9941 else if(x>300*mul && !bdown)
9942 {
9943 if(y<224*mul && first>0)
9944 {
9945 first-=TILES_PER_PAGE;
9946 redraw=true;
9947 }
9948
9949 if(y>=224*mul && first<TILES_PER_PAGE*(TILE_PAGES-1))
9950 {
9951 first+=TILES_PER_PAGE;
9952 redraw=true;
9953 }
9954
9955 bdown=true;
9956 }
9957
9958 if(type==1||type==2)
9959 {
9960 if(!bdown && isinRect(x,y,8*mul,216*mul+panel_yofs,23*mul,231*mul+panel_yofs))
9961 done=1;
9962
9963 if(!bdown && isinRect(x,y,148*mul,216*mul+panel_yofs,163*mul,231*mul+panel_yofs))
9964 done=2;
9965 }
9966 else if(!bdown && isinRect(x,y,127*mul,216*mul+panel_yofs,(127+15)*mul,(216+15)*mul+panel_yofs))
9967 {
9968 rect_sel=!rect_sel;
9969 copy=-1;
9970 redraw=true;
9971 }
9972 else if(!bdown && isinRect(x,y,150*mul,213*mul+panel_yofs,(150+28)*mul,(213+21)*mul+panel_yofs))
9973 {
9974 FONT *tf = font;
9975 font = tfont;
9976
9977 if(do_text_button(150*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Grab"))
9978 {
9979 font = tf;
9980 grab_tile(tile,cs);
9981 draw_tile_list_window();
9982 position_mouse_z(0);
9983 redraw=true;
9984 }
9985
9986 font = tf;
9987 }
9988 else if(!bdown && isinRect(x,y,(150+28)*mul,213*mul+panel_yofs,(150+28*2)*mul,(213+21)*mul+panel_yofs+21))
9989 {
9990 FONT *tf = font;
9991 font = tfont;
9992
9993 if(do_text_button((150+28)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Edit"))
9994 {
9995 font = tf;
9996 edit_tile(tile,flip,cs);
9997 draw_tile_list_window();
9998 redraw=true;
9999 }
10000
10001 font = tf;
10002 }
10003 else if(!bdown && isinRect(x,y,(150+28*2)*mul,213*mul+panel_yofs,(150+28*3)*mul,(213+21)*mul+panel_yofs))
10004 {
10005 FONT *tf = font;
10006 font = tfont;
10007
10008 if(do_text_button((150+28*2)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Export"))
10009 {
10010 strcpy(datapath, "tileset.png");
10011 if(getname("Export Tile Page (.png)","png",NULL,datapath,true))
10012 {
10013 PALETTE temppal;
10014 get_palette(temppal);
10015 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
10016 draw_tiles(tempbmp,first,cs,f,false,true);
10017 save_bitmap(temppath, tempbmp, RAMpal);
10018 destroy_bitmap(tempbmp);
10019 }
10020 }
10021
10022 font = tf;
10023 }
10024 else if(!bdown && isinRect(x,y,(150+28*3)*mul,213*mul+panel_yofs,(150+28*4)*mul,(213+21)*mul+panel_yofs))
10025 {
10026 FONT *tf = font;
10027 font = tfont;
10028
10029 if(do_text_button((150+28*3)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Recolor"))
10030 {
10031 if(massRecolorSetup(cs))
10032 {
10033 go_tiles();
10034
10035 FOREACH_START(t)
10036 massRecolorApply(t);
10037 FOREACH_END
10038
10039 register_blank_tiles();
10040 }
10041 }
10042
10043 font = tf;
10044 }
10045 else if(!bdown && isinRect(x,y,(150+28*4)*mul,213*mul+panel_yofs,(150+28*5)*mul,(213+21)*mul+panel_yofs))
10046 {
10047 FONT *tf = font;
10048 font = tfont;
10049
10050 if(do_text_button((150+28*4)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Done"))
10051 {
10052 done=1;
10053 }
10054
10055 font = tf;
10056 }
10057
10058 bdown=true;
10059 }
10060
10061 bool r_click = false;
10062
10063 if(gui_mouse_b()&2 && !bdown && type==0)
10064 {
10065 int32_t x=(gui_mouse_x()-screen_xofs);//&0xFF0;
10066 int32_t y=(gui_mouse_y()-screen_yofs);//&0xF0;
10067
10068 if(y>=0 && y<208*mul)
10069 {
10070 x=zc_min(zc_max(x,0),(320*mul)-1);
10071 int32_t t = ((y)>>(5))*TILES_PER_ROW + ((x)>>(5)) + first;
10072
10073 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
10074 tile=tile2=t;
10075 }
10076
10077 bdown = r_click = true;
10078 f=8;
10079 }
10080
10081 if(gui_mouse_b()==0)
10082 bdown=false;
10083
10084 position_mouse_z(0);
10085
10086 REDRAW:
10087
10088 if((f%8)==0 || InvalidBG == 1)
10089 redraw=true;
10090 if(otl != tile || otl2 != tile2)
10091 {
10092 otl = tile;
10093 otl2 = tile2;
10094 redraw = true;
10095 }
10096
10097 if(redraw)
10098 {
10099 draw_tiles(first,cs,f);
10100 }
10101 if(f&8)
10102 {
10103 if(rect_sel)
10104 {
10105 for(int32_t i=zc_min(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10106 zc_min(TILECOL(tile),TILECOL(tile2));
10107 i<=zc_max(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10108 zc_max(TILECOL(tile),TILECOL(tile2)); i++)
10109 {
10110 if(i>=first && i<first+TILES_PER_PAGE &&
10111 TILECOL(i)>=zc_min(TILECOL(tile),TILECOL(tile2)) &&
10112 TILECOL(i)<=zc_max(TILECOL(tile),TILECOL(tile2)))
10113 {
10114 int32_t x=TILECOL(i)<<(5);
10115 int32_t y=TILEROW(i-first)<<(5);
10116 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10117 }
10118 }
10119 }
10120 else
10121 {
10122 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
10123 {
10124 if(i>=first && i<first+TILES_PER_PAGE)
10125 {
10126 int32_t x=TILECOL(i)<<(5);
10127 int32_t y=TILEROW(i-first)<<(5);
10128 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10129 }
10130 }
10131 }
10132 }
10133
10134 if(type==0)
10135 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
10136 else
10137 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
10138
10139 if(type==2)
10140 {
10141 char cbuf[16];
10142 sprintf(cbuf, "E&xtend: %s",ex==2 ? "32x32" : ex==1 ? "32x16" : "16x16");
10143 gui_textout_ln(screen, get_zc_font(font_lfont_l), (uint8_t *)cbuf, (235*mul)+screen_xofs, (212*mul)+screen_yofs+panel_yofs, jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
10144 }
10145
10146 ++f;
10147
10148 if(r_click)
10149 {
10150 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_USED, HIDE_USED);
10151 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_UNUSED, HIDE_UNUSED);
10152 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_BLANK, HIDE_BLANK);
10153 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_8BIT, HIDE_8BIT_MARKER);
10154 NewMenu rcmenu
10155 {
10156 { "Copy", [&]()
10157 {
10158 copy = zc_min(tile,tile2);
10159 copycnt = abs(tile-tile2)+1;
10160 } },
10161 { "Paste", [&]()
10162 {
10163 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, false);
10164 if(saved) saved = !b;
10165 }, nullopt, copy < 0 },
10166 { "Move", [&]()
10167 {
10168 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, true);
10169 if(saved) saved = !b;
10170 }, nullopt, copy < 0 },
10171 { "Clear", [&]()
10172 {
10173 delete_tiles(tile, tile2, rect_sel);
10174 } },
10175 {},
10176 { "Edit", [&]()
10177 {
10178 edit_tile(tile, flip, cs);
10179 draw_tile_list_window();
10180 } },
10181 { "Grab", [&]()
10182 {
10183 grab_tile(tile, cs);
10184 draw_tile_list_window();
10185 position_mouse_z(0);
10186 } },
10187 { "Scale", [&]()
10188 {
10189 bool b = scale_or_rotate_tiles(tile, tile2, cs, false);
10190 if(saved) saved = !b;
10191 }, nullopt, type != 0 },
10192 { "Angular Rotation", [&]()
10193 {
10194 bool b = scale_or_rotate_tiles(tile, tile2, cs, true);
10195 if(saved) saved = !b;
10196 }, nullopt, type != 0 },
10197 { "Color Depth", [&]()
10198 {
10199 do_convert_tile(tile, tile2, cs, rect_sel,
10200 (newtilebuf[tile].format!=tf4Bit), false, false);
10201 } },
10202 {},
10203 { "Blank?", [&]()
10204 {
10205 show_blank_tile(tile);
10206 } },
10207 {},
10208 { "View ", &select_tile_view_menu },
10209 { "Overlay", [&]()
10210 {
10211 overlay_tile(newtilebuf, tile, copy, cs, 0);
10212 } },
10213 { "H-Flip", [&]()
10214 {
10215 flip ^= 1;
10216 go_tiles();
10217
10218 if(type == 0)
10219 {
10220 normalize(tile, tile2, rect_sel, flip);
10221 flip = 0;
10222 }
10223 } },
10224 { "V-Flip", [&]()
10225 {
10226 flip ^= 2;
10227 go_tiles();
10228
10229 if(type == 0)
10230 {
10231 normalize(tile, tile2, rect_sel, flip);
10232 flip = 0;
10233 }
10234 } },
10235 { "Create Combos", [&]()
10236 {
10237 if(rect_sel)
10238 make_combos_rect(top, left, rows, columns, cs);
10239 else
10240 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
10241 }, nullopt, type != 0 },
10242 { "Insert", [&]()
10243 {
10244 bool warn = (rect_sel
10245 && ((tile/20)!=(tile2/20))
10246 && !(tile%20==0&&tile2%20==19));
10247 int32_t z = zc_min(tile, tile2);
10248 int32_t count = abs(tile-tile2) + 1;
10249 tile = z;
10250 tile2 = NEWMAXTILES;
10251 copy = tile + count;
10252 copycnt = NEWMAXTILES-copy;
10253
10254 string msg;
10255
10256 if(count>1)
10257 msg = fmt::format("Insert {} blank tiles?",count);
10258 else
10259 msg = "Insert a blank tile?";
10260
10261 AlertDialog("Insert Tiles", msg
10262 +"\nThis will offset the tiles that follow!"
10263 +(warn?"\nInserting tiles ignores rectangular selections!":""),
10264 [&](bool ret,bool)
10265 {
10266 if(ret)
10267 {
10268 go_tiles();
10269 if(copy_tiles(copy, tile2, tile, copycnt, false, true))
10270 saved = false;
10271 }
10272 }).show();
10273
10274 copy=-1;
10275 tile2=tile=z;
10276 }, nullopt, type != 0 },
10277 { "Remove", [&]()
10278 {
10279 bool warn = (rect_sel
10280 && ((tile/20)!=(tile2/20))
10281 && !(tile%20==0&&tile2%20==19));
10282 int32_t z = zc_min(tile, tile2);
10283 int32_t count = abs(tile-tile2) + 1;
10284 tile = z;
10285 tile2 = NEWMAXTILES;
10286 copy = tile + count;
10287 copycnt = NEWMAXTILES-copy;
10288
10289 string msg;
10290
10291 if(count>1)
10292 msg = fmt::format("Remove tiles {} - {}?", tile, copy-1);
10293 else
10294 msg = fmt::format("Remove tile {}?", tile);
10295
10296 AlertDialog("Remove Tiles", msg
10297 +"\nThis will offset the tiles that follow!"
10298 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
10299 [&](bool ret,bool)
10300 {
10301 if(ret)
10302 {
10303 go_tiles();
10304 if(copy_tiles(tile, tile2, copy, copycnt, false, true))
10305 saved = false;
10306 }
10307 }).show();
10308
10309 copy=-1;
10310 tile2=tile=z;
10311 }, nullopt, type != 0 },
10312 };
10313 rcmenu.pop(window_mouse_x(),window_mouse_y());
10314 redraw = true;
10315 r_click = false;
10316 goto REDRAW;
10317 }
10318 update_hw_screen();
10319 }
10320 while(!done);
10321
10322 while(gui_mouse_b())
10323 {
10324 /* do nothing */
10325 rest(1);
10326 }
10327
10328 comeback();
10329 register_blank_tiles();
10330 register_used_tiles();
10331 setup_combo_animations();
10332 setup_combo_animations2();
10333 int32_t ret = done-1;
10334 if(ret)
10335 {
10336 _selected_tile = tile;
10337 _selected_tcset = cs;
10338 }
10339
10340 popup_zqdialog_end();
10341 return ret;
10342 }
10343 int32_t select_tile_2(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
10344 {
10345 if(_selected_tile > -1)
10346 {
10347 tile = _selected_tile;
10348 cs = _selected_tcset;
10349 }
10350 int32_t ret = select_tile(tile,flip,type,cs,edit_cs,exnow,always_use_flip);
10351 if(_selected_tile < 0)
10352 {
10353 _selected_tile = tile;
10354 _selected_tcset = cs;
10355 }
10356 return ret;
10357 }
10358
10359 int32_t onTiles()
10360 {
10361 return onGotoTiles(-1);
10362 }
10363
10364 int32_t onGotoTiles(int32_t startfrom)
10365 {
10366 static int32_t t = 0;
10367 if (startfrom > -1)
10368 t = startfrom;
10369 int32_t f = 0;
10370 int32_t c = CSet;
10371 reset_pal_cycling();
10372 // loadlvlpal(Map.CurrScr()->color);
10373 rebuild_trans_table();
10374 select_tile(t, f, 0, c, true);
10375 refresh(rALL);
10376 return D_O_K;
10377 }
10378
10379 int32_t combopage_animate = 1;
10380 void draw_combo(BITMAP *dest, int x,int y,int c,int cs,bool animate)
10381 {
10382 if(unsigned(c)<MAXCOMBOS)
10383 {
10384 newcombo& cmb = combobuf[c];
10385 int t = cmb.tile;
10386 if(!animate)
10387 cmb.tile = cmb.o_tile;
10388 put_combo(dest,x,y,c,cs,0,0);
10389 cmb.tile = t;
10390 }
10391 else
10392 {
10393 rectfill(dest,x,y,x+32-1,y+32-1,0);
10394 }
10395 }
10396
10397 void draw_combos(int32_t page,int32_t cs,bool cols)
10398 {
10399 clear_bitmap(screen2);
10400 BITMAP *buf = create_bitmap_ex(8,16,16);
10401
10402 int32_t w = 32;
10403 int32_t h = 32;
10404 int32_t mul = 2;
10405
10406 int32_t window_xofs=(zq_screen_w-640-12)>>1;
10407 int32_t window_yofs=(zq_screen_h-480-25-6)>>1;
10408 int32_t screen_xofs=window_xofs+6;
10409 int32_t screen_yofs=window_yofs+25;
10410
10411 if(cols==false)
10412 {
10413 for(int32_t i=0; i<256; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
10414 {
10415 int32_t x = (i%COMBOS_PER_ROW)*w;
10416 int32_t y = (i/COMBOS_PER_ROW)*h;
10417
10418 combotile_override_x = x+screen_xofs+(w-16)/2;
10419 combotile_override_y = y+screen_yofs+(h-16)/2;
10420 draw_combo(buf,0,0,i+(page<<8),cs,combopage_animate);
10421 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10422 }
10423 }
10424 else
10425 {
10426 int32_t c = 0;
10427
10428 for(int32_t i=0; i<256; i++)
10429 {
10430 int32_t x = (i%COMBOS_PER_ROW)*w;
10431 int32_t y = (i/COMBOS_PER_ROW)*h;
10432
10433 combotile_override_x = x+screen_xofs+(w-16)/2;
10434 combotile_override_y = y+screen_yofs+(h-16)/2;
10435 draw_combo(buf,0,0,c+(page<<8),cs,combopage_animate);
10436 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10437 ++c;
10438
10439 if((i&3)==3)
10440 c+=48;
10441
10442 if((i%COMBOS_PER_ROW)==(COMBOS_PER_ROW-1))
10443 c-=256;
10444 }
10445 }
10446 combotile_override_x = combotile_override_y = -1;
10447
10448 for(int32_t x=(64*mul); x<(320*mul); x+=(64*mul))
10449 {
10450 _allegro_vline(screen2,x,0,(208*mul)-1,vc(15));
10451 }
10452
10453 destroy_bitmap(buf);
10454 }
10455
10456 void combo_info(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,int32_t buttons)
10457 {
10458 int32_t yofs=3;
10459 static BITMAP *buf = create_bitmap_ex(8,16,16);
10460 int32_t mul = 2;
10461 FONT *tfont = get_zc_font(font_lfont_l);
10462
10463 rectfill(screen2,0,210*2,(320*2)-1,(240*2)-1,jwin_pal[jcBOX]);
10464 _allegro_hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
10465 _allegro_hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
10466
10467 jwin_draw_frame(screen2,(31*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10468
10469 if(copy>=0)
10470 {
10471 put_combo(buf,0,0,copy,cs,0,0);
10472 stretch_blit(buf,screen2,0,0,16,16,31*mul,216*mul+yofs,16*mul,16*mul);
10473
10474 if(copycnt>1)
10475 {
10476 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
10477 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
10478 }
10479 else
10480 {
10481 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
10482 }
10483 }
10484 else
10485 {
10486 if (InvalidBG == 2)
10487 {
10488 draw_checkerboard(screen2, 31 * mul, 216 * mul + yofs, 16 * mul);
10489 }
10490 else if(InvalidBG == 1)
10491 {
10492 for(int32_t dy=0; dy<16*mul; dy++)
10493 {
10494 for(int32_t dx=0; dx<16*mul; dx++)
10495 {
10496 screen2->line[(216*mul)+yofs+dy][(31*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10497 }
10498 }
10499 }
10500 else
10501 {
10502 rectfill(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(0));
10503 rect(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10504 line(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10505 line(screen2, (31*mul), (216*mul)+yofs+31, (31*mul)+31, (216*mul)+yofs, vc(15));
10506 }
10507 }
10508
10509 jwin_draw_frame(screen2,(53*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10510 put_combo(buf,0,0,tile,cs,0,0);
10511 stretch_blit(buf,screen2,0,0,16,16,53*mul,216*mul+yofs,16*mul,16*mul);
10512
10513 if(tile>tile2)
10514 {
10515 zc_swap(tile,tile2);
10516 }
10517
10518 char cbuf[8];
10519 cbuf[0]=0;
10520
10521 if(tile2!=tile)
10522 {
10523 sprintf(cbuf,"-%d",tile2);
10524 }
10525
10526 textprintf_ex(screen2,tfont,(73*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"combo: CSet %d", cs);
10527 textprintf_ex(screen2,tfont,(73*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,cbuf);
10528
10529 if(tile2==tile)
10530 {
10531 int32_t nextcombo=combobuf[tile].nextcombo;
10532 int32_t nextcset=(combobuf[tile].animflags & AF_CYCLENOCSET) ? cs : combobuf[tile].nextcset;
10533 jwin_draw_frame(screen2,(136*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10534
10535 if(nextcombo>0)
10536 {
10537 put_combo(buf,0,0,nextcombo,nextcset,0,0);
10538 stretch_blit(buf,screen2,0,0,16,16,136*mul,216*mul+yofs,16*mul,16*mul);
10539 }
10540 else
10541 {
10542 if (InvalidBG == 2)
10543 {
10544 draw_checkerboard(screen2, 136 * mul, 216 * mul + yofs, 16 * mul);
10545 }
10546 else if(InvalidBG == 1)
10547 {
10548 for(int32_t dy=0; dy<16*mul; dy++)
10549 {
10550 for(int32_t dx=0; dx<16*mul; dx++)
10551 {
10552 screen2->line[(216*mul)+yofs+dy][(136*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10553 }
10554 }
10555 }
10556 else
10557 {
10558 rectfill(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(0));
10559 rect(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10560 line(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10561 line(screen2, (136*mul), (216*mul)+yofs+31, (136*mul)+31, (216*mul)+yofs, vc(15));
10562 }
10563 }
10564
10565 textprintf_right_ex(screen2,tfont,(132*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Cycle:");
10566 textprintf_right_ex(screen2,tfont,(132*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",nextcombo);
10567 }
10568
10569
10570 FONT *tf = font;
10571 font = tfont;
10572
10573 draw_checkbox(screen2,320,440+yofs,16,combopage_animate);
10574 textprintf_ex(screen2,tfont,320+18,440+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Animate");
10575
10576 if(buttons&2)
10577 {
10578 draw_text_button(screen2,404,426+yofs,88,42,"Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10579 }
10580
10581 if(buttons&4)
10582 {
10583 draw_text_button(screen2,494,426+yofs,88,42,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10584 }
10585
10586 font = tf;
10587
10588 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
10589 textprintf_ex(screen2,tfont,(293*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
10590 textprintf_centre_ex(screen2,tfont,(309*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
10591 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
10592
10593 int32_t w = 640;
10594 int32_t h = 480;
10595 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10596 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10597 int32_t screen_xofs=window_xofs+6;
10598 int32_t screen_yofs=window_yofs+25;
10599
10600 custom_vsync();
10601 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
10602 SCRFIX();
10603 //destroy_bitmap(buf);
10604 }
10605
10606 void sel_combo(int32_t &tile, int32_t &tile2, int32_t s, bool cols)
10607 {
10608 int32_t page = tile&0xFF00;
10609 tile &= 0xFF;
10610
10611 if(!cols)
10612 tile += s;
10613 else
10614 {
10615 if(s==-COMBOS_PER_ROW)
10616 tile-=4;
10617
10618 if(s==COMBOS_PER_ROW)
10619 tile+=4;
10620
10621 if(s==-1)
10622 tile-=1;
10623
10624 if(s==1)
10625 tile+=1;
10626 }
10627
10628 /*
10629 if(s==1)
10630 {
10631 if((tile&3)==3)
10632 tile+=48;
10633 else
10634 ++tile;
10635 }
10636 if(s==-1)
10637 {
10638 if((tile&3)==0)
10639 tile-=48;
10640 else
10641 --tile;
10642 }
10643 }
10644 */
10645 bound(tile,0,255);
10646 tile += page;
10647
10648 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
10649 tile2 = tile;
10650 }
10651
10652 void draw_combo_list_window()
10653 {
10654 int32_t window_xofs=0;
10655 int32_t window_yofs=0;
10656 int32_t w = 640;
10657 int32_t h = 480;
10658
10659 window_xofs=(zq_screen_w-w-12)>>1;
10660 window_yofs=(zq_screen_h-h-25-6)>>1;
10661 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
10662 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
10663 FONT *oldfont = font;
10664 font = get_zc_font(font_lfont);
10665 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Combo", true);
10666 font=oldfont;
10667 }
10668
10669
10670 static int32_t _selected_combo=-1, _selected_cset=-1;
10671 bool select_combo_2(int32_t &cmb,int32_t &cs)
10672 {
10673 popup_zqdialog_start();
10674 reset_combo_animations();
10675 reset_combo_animations2();
10676 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
10677 // static int32_t cmb=0;
10678 int32_t page=cmb>>8;
10679 int32_t tile2=cmb;
10680 int32_t done=0;
10681 int32_t tile_clicked=-1;
10682 int32_t t2;
10683 // int32_t cs = CSet;
10684 int32_t copy=-1;
10685 int32_t copycnt=0;
10686
10687 position_mouse_z(0);
10688
10689 go();
10690 int32_t w = 640;
10691 int32_t h = 480;
10692 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10693 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10694 int32_t screen_xofs=window_xofs+6;
10695 int32_t screen_yofs=window_yofs+25;
10696 int32_t panel_yofs=3;
10697 int32_t mul = 2;
10698 FONT *tfont = get_zc_font(font_lfont_l);
10699
10700 draw_combo_list_window();
10701 draw_combos(page,cs,combo_cols);
10702 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
10703
10704 while(gui_mouse_b())
10705 {
10706 /* do nothing */
10707 rest(1);
10708 }
10709
10710 bool bdown=false;
10711 int32_t f=0;
10712 int otl = cmb, otl2 = tile2;
10713
10714 do
10715 {
10716 HANDLE_CLOSE_ZQDLG();
10717 if(exiting_program) break;
10718 rest(4);
10719 bool redraw=false;
10720
10721 if(mouse_z<0)
10722 {
10723 if(page<COMBO_PAGES-1)
10724 {
10725 ++page;
10726 cmb=tile2=(page<<8)+(cmb&0xFF);
10727 }
10728
10729 position_mouse_z(0);
10730 redraw=true;
10731 }
10732 else if(mouse_z>0)
10733 {
10734 if(page>0)
10735 {
10736 --page;
10737 cmb=tile2=(page<<8)+(cmb&0xFF);
10738 }
10739
10740 position_mouse_z(0);
10741 redraw=true;
10742 }
10743
10744 if(keypressed())
10745 {
10746 switch(readkey()>>8)
10747 {
10748 case KEY_DEL:
10749 cmb=0;
10750 done=2;
10751 break;
10752
10753 case KEY_ENTER_PAD:
10754 case KEY_ENTER:
10755 done=2;
10756 break;
10757
10758 case KEY_ESC:
10759 done=1;
10760 break;
10761
10762 case KEY_F1:
10763 onHelp();
10764 break;
10765
10766 case KEY_SPACE:
10767 combo_cols=!combo_cols;
10768 redraw=true;
10769 break;
10770
10771 case KEY_EQUALS:
10772 case KEY_PLUS_PAD:
10773 cs = (cs<13) ? cs+1:0;
10774 redraw=true;
10775 break;
10776
10777 case KEY_MINUS:
10778 case KEY_MINUS_PAD:
10779 cs = (cs>0) ? cs-1:13;
10780 redraw=true;
10781 break;
10782
10783 case KEY_UP:
10784 sel_combo(cmb,tile2,-COMBOS_PER_ROW,combo_cols);
10785 redraw=true;
10786 break;
10787
10788 case KEY_DOWN:
10789 sel_combo(cmb,tile2,COMBOS_PER_ROW,combo_cols);
10790 redraw=true;
10791 break;
10792
10793 case KEY_LEFT:
10794 sel_combo(cmb,tile2,-1,combo_cols);
10795 redraw=true;
10796 break;
10797
10798 case KEY_RIGHT:
10799 sel_combo(cmb,tile2,1,combo_cols);
10800 redraw=true;
10801 break;
10802
10803 case KEY_PGUP:
10804 if(page>0)
10805 {
10806 --page;
10807 cmb=tile2=(page<<8)+(cmb&0xFF);
10808 }
10809
10810 redraw=true;
10811 break;
10812
10813 case KEY_PGDN:
10814 if(page<COMBO_PAGES-1)
10815 {
10816 ++page;
10817 cmb=tile2=(page<<8)+(cmb&0xFF);
10818 }
10819
10820 redraw=true;
10821 break;
10822
10823 case KEY_P:
10824 {
10825 int32_t choosepage=getnumber("Goto Page", (PreFillComboEditorPage?page:0));
10826
10827 if(!cancelgetnum)
10828 page=(zc_min(choosepage,COMBO_PAGES-1));
10829
10830 cmb=tile2=(page<<8)+(cmb&0xFF);
10831 redraw=true;
10832 break;
10833 }
10834 }
10835
10836 clear_keybuf();
10837 }
10838
10839 if(gui_mouse_b()&1)
10840 {
10841 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
10842 {
10843 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
10844 {
10845 done=1;
10846 }
10847 }
10848
10849 int32_t x=gui_mouse_x()-screen_xofs;
10850 int32_t y=gui_mouse_y()-screen_yofs;
10851
10852 if(y>=0 && y<208*mul)
10853 {
10854 x=zc_min(zc_max(x,0),(320*mul)-1);
10855 int32_t t;
10856
10857 if(!combo_cols)
10858 {
10859 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
10860 }
10861 else
10862 {
10863 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10864 }
10865
10866 bound(t,0,255);
10867 t+=page<<8;
10868 cmb=tile2=t;
10869
10870 if(tile_clicked!=t)
10871 {
10872 dclick_status=DCLICK_NOT;
10873 }
10874 else if(dclick_status == DCLICK_AGAIN)
10875 {
10876 while(gui_mouse_b())
10877 {
10878 /* do nothing */
10879 }
10880
10881 if(!combo_cols)
10882 {
10883 t2 = (y>>5)*COMBOS_PER_ROW + (x>>5);
10884 }
10885 else
10886 {
10887 t2 = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10888 }
10889
10890 if(t2!=t)
10891 {
10892 dclick_status=DCLICK_NOT;
10893 }
10894 else
10895 {
10896 done=2;
10897 }
10898 }
10899
10900 tile_clicked=t;
10901 }
10902 else if(y>=(208*mul) && x>(300*mul) && !bdown)
10903 {
10904 if(y<(224*mul)+panel_yofs && page>0)
10905 {
10906 --page;
10907 redraw=true;
10908 }
10909
10910 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
10911 {
10912 ++page;
10913 redraw=true;
10914 }
10915
10916 bdown=true;
10917 }
10918
10919 if(!bdown && isinRect(x,y,(247*mul),(213*mul),((247+44)*mul),((213+21)*mul)))
10920 {
10921 FONT *tf = font;
10922 font = tfont;
10923
10924 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
10925 {
10926 done=2;
10927 }
10928
10929 font = tf;
10930 }
10931 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
10932 {
10933 FONT *tf = font;
10934 font = tfont;
10935
10936 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
10937 combopage_animate = combopage_animate ? 0 : 1;
10938 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
10939 redraw = true;
10940
10941 font = tf;
10942 }
10943
10944 bdown=true;
10945 }
10946
10947 bool r_click = false;
10948
10949 if(gui_mouse_b()&2 && !bdown)
10950 {
10951 int32_t x=gui_mouse_x()+screen_xofs;
10952 int32_t y=gui_mouse_y()+screen_yofs;
10953
10954 if(y>=0 && y<208*mul)
10955 {
10956 x=zc_min(zc_max(x,0),(320*mul)-1);
10957 int32_t t;
10958
10959 if(!combo_cols)
10960 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
10961 else
10962 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10963
10964 bound(t,0,255);
10965 t+=page<<8;
10966
10967 if(t<zc_min(cmb,tile2) || t>zc_max(cmb,tile2))
10968 cmb=tile2=t;
10969 }
10970
10971 bdown = r_click = true;
10972 f=8;
10973 }
10974
10975 if(gui_mouse_b()==0)
10976 bdown=false;
10977
10978 if((f%8) || InvalidBG == 1)
10979 redraw = true;
10980 if(otl != cmb || otl2 != tile2)
10981 {
10982 otl = cmb;
10983 otl2 = tile2;
10984 redraw = true;
10985 }
10986
10987 if(redraw || combopage_animate)
10988 draw_combos(page,cs,combo_cols);
10989
10990 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
10991
10992 if(f&8)
10993 {
10994 int32_t x,y;
10995
10996 for(int32_t i=zc_min(cmb,tile2); i<=zc_max(cmb,tile2); i++)
10997 {
10998 if((i>>8)==page)
10999 {
11000 int32_t t=i&255;
11001
11002 if(!combo_cols)
11003 {
11004 x=(t%COMBOS_PER_ROW)<<5;
11005 y=(t/COMBOS_PER_ROW)<<5;
11006 }
11007 else
11008 {
11009 x=((t&3) + ((t/52)<<2)) << 5;
11010 y=((t%52)>>2) << 5;
11011 }
11012
11013 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11014 }
11015 }
11016
11017 SCRFIX();
11018 }
11019
11020 ++f;
11021
11022 }
11023 while(!done);
11024
11025 while(gui_mouse_b())
11026 {
11027 /* do nothing */
11028 rest(1);
11029 }
11030
11031 comeback();
11032 setup_combo_animations();
11033 setup_combo_animations2();
11034
11035 bool ret = done==2;
11036 if(ret)
11037 {
11038 _selected_combo = cmb;
11039 _selected_cset = cs;
11040 }
11041
11042 popup_zqdialog_end();
11043 return ret;
11044 }
11045
11046 bool select_combo_3(int32_t &cmb,int32_t &cs)
11047 {
11048 if(_selected_combo < 0)
11049 {
11050 _selected_combo = Combo;
11051 _selected_cset = CSet;
11052 }
11053 cmb = _selected_combo;
11054 cs = _selected_cset;
11055 return select_combo_2(cmb,cs);
11056 }
11057
11058 bool advpaste(int32_t tile, int32_t tile2, int32_t copy)
11059 {
11060 static bitstring pasteflags;
11061 static const vector<CheckListInfo> advp_names =
11062 {
11063 { "Tile" },
11064 { "CSet2" },
11065 { "Solidity" },
11066 { "Animation" },
11067 { "Type" },
11068 { "Inherent Flag" },
11069 { "Attribytes" },
11070 { "Attrishorts" },
11071 { "Attributes" },
11072 { "Flags", "The 16 Flags on the 'Flags' tab" },
11073 { "Gen. Flags", "The 2 'General Flags' on the 'Flags' tab" },
11074 { "Label" },
11075 { "Script" },
11076 { "Effect" },
11077 { "Triggers Tab" },
11078 { "Lifting Tab" },
11079 { "Gen: Movespeed", "The Movespeed related values from the 'General' tab" },
11080 { "Gen: SFX", "The SFX related values from the 'General' tab" },
11081 { "Gen: Sprites", "The Sprites related values from the 'General' tab" },
11082 };
11083 if(!call_checklist_dialog("Advanced Paste",advp_names,pasteflags))
11084 return false;
11085
11086 //Paste to each combo in the range
11087 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11088 {
11089 combobuf[i].advpaste(combobuf[copy], pasteflags);
11090 }
11091
11092 if(pasteflags.get(CMB_ADVP_TILE)) //reset animations if needed
11093 {
11094 setup_combo_animations();
11095 setup_combo_animations2();
11096 }
11097
11098 return true;
11099 }
11100
11101 int32_t combo_screen(int32_t pg, int32_t tl)
11102 {
11103 popup_zqdialog_start();
11104 reset_combo_animations();
11105 reset_combo_animations2();
11106 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
11107 static int32_t tile=0;
11108 static int32_t page=0;
11109
11110 if(pg>-1)
11111 page = pg;
11112
11113 if(tl>-1)
11114 tile = tl;
11115
11116 int32_t tile2=tile;
11117 int32_t done=0;
11118 int32_t cs = CSet;
11119 int32_t copy=-1;
11120 int32_t copycnt=0;
11121
11122 int32_t tile_clicked=-1;
11123 int32_t t2;
11124
11125 bool masscopy;
11126
11127 go();
11128 int32_t w = 640;
11129 int32_t h = 480;
11130 int32_t window_xofs=(zq_screen_w-w-12)>>1;
11131 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
11132 int32_t screen_xofs=window_xofs+6;
11133 int32_t screen_yofs=window_yofs+25;
11134 int32_t panel_yofs=3;
11135 int32_t mul = 2;
11136 FONT *tfont = get_zc_font(font_lfont_l);
11137
11138 draw_combo_list_window();
11139 draw_combos(page,cs,combo_cols);
11140 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11141 go_combos();
11142 position_mouse_z(0);
11143
11144 while(gui_mouse_b())
11145 {
11146 /* do nothing */
11147 }
11148
11149 bool bdown=false;
11150 int32_t f=0;
11151 int otl = tile, otl2 = tile2;
11152
11153 do
11154 {
11155 HANDLE_CLOSE_ZQDLG();
11156 if(exiting_program) break;
11157 rest(4);
11158 bool redraw=false;
11159
11160 if(mouse_z<0)
11161 {
11162 if(page<COMBO_PAGES-1)
11163 {
11164 ++page;
11165 tile=tile2=(page<<8)+(tile&0xFF);
11166 }
11167
11168 position_mouse_z(0);
11169 redraw=true;
11170 }
11171 else if(mouse_z>0)
11172 {
11173 if(page>0)
11174 {
11175 --page;
11176 tile=tile2=(page<<8)+(tile&0xFF);
11177 }
11178
11179 position_mouse_z(0);
11180 redraw=true;
11181 }
11182
11183 if(keypressed())
11184 {
11185 switch(readkey()>>8)
11186 {
11187 case KEY_ENTER_PAD:
11188 case KEY_ENTER:
11189 done=2;
11190 break;
11191
11192 case KEY_ESC:
11193 done=1;
11194 break;
11195
11196 case KEY_F1:
11197 onHelp();
11198 break;
11199
11200 case KEY_SPACE:
11201 combo_cols=!combo_cols;
11202 redraw=true;
11203 break;
11204
11205 case KEY_EQUALS:
11206 case KEY_PLUS_PAD:
11207 if(CHECK_CTRL_CMD)
11208 {
11209 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11210 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11211 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11212
11213 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11214 {
11215 combobuf[i].set_tile(wrap(combobuf[i].o_tile + amnt,
11216 0, NEWMAXTILES-1));
11217 }
11218
11219 setup_combo_animations();
11220 redraw=true;
11221 }
11222 else
11223 {
11224 cs = (cs<13) ? cs+1:0;
11225 redraw=true;
11226 }
11227
11228 break;
11229
11230 case KEY_MINUS:
11231 case KEY_MINUS_PAD:
11232 if(CHECK_CTRL_CMD)
11233 {
11234 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11235 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11236 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11237
11238 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11239 {
11240 combobuf[i].set_tile(wrap(combobuf[i].o_tile - amnt,
11241 0, NEWMAXTILES-1));
11242 }
11243
11244 setup_combo_animations();
11245 redraw=true;
11246 }
11247 else
11248 {
11249 cs = (cs>0) ? cs-1:13;
11250 redraw=true;
11251 }
11252
11253 break;
11254
11255 case KEY_UP:
11256 sel_combo(tile,tile2,-COMBOS_PER_ROW,combo_cols);
11257 redraw=true;
11258 break;
11259
11260 case KEY_DOWN:
11261 sel_combo(tile,tile2,COMBOS_PER_ROW,combo_cols);
11262 redraw=true;
11263 break;
11264
11265 case KEY_LEFT:
11266 sel_combo(tile,tile2,-1,combo_cols);
11267 redraw=true;
11268 break;
11269
11270 case KEY_RIGHT:
11271 sel_combo(tile,tile2,1,combo_cols);
11272 redraw=true;
11273 break;
11274
11275 case KEY_PGUP:
11276 if(page>0)
11277 {
11278 --page;
11279 tile=tile2=(page<<8)+(tile&0xFF);
11280 }
11281
11282 redraw=true;
11283 break;
11284
11285 case KEY_PGDN:
11286 if(page<COMBO_PAGES-1)
11287 {
11288 ++page;
11289 tile=tile2=(page<<8)+(tile&0xFF);
11290 }
11291
11292 redraw=true;
11293 break;
11294
11295 case KEY_A:
11296 {
11297 tile=(page<<8);
11298 tile2=(page<<8)+(0xFF);
11299 }
11300
11301 redraw=true;
11302 break;
11303
11304 case KEY_P:
11305 {
11306 int32_t choosepage = getnumber("Goto Page", (PreFillComboEditorPage?page:0));
11307
11308 if(!cancelgetnum)
11309 page=(zc_min(choosepage,COMBO_PAGES-1));
11310
11311 tile=tile2=(page<<8)+(tile&0xFF);
11312 redraw=true;
11313 }
11314 break;
11315
11316 case KEY_U:
11317 comeback_combos();
11318 redraw=true;
11319 break;
11320
11321 case KEY_E:
11322 go_combos();
11323 edit_combo(tile,false,cs);
11324 redraw=true;
11325 setup_combo_animations();
11326 setup_combo_animations2();
11327 break;
11328
11329 case KEY_C:
11330 go_combos();
11331 copy=zc_min(tile,tile2);
11332 copycnt=abs(tile-tile2)+1;
11333 redraw=true;
11334 break;
11335
11336 case KEY_H:
11337 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11338 {
11339 combobuf[i].flip^=1;
11340 byte w2=combobuf[i].walk;
11341 combobuf[i].walk=((w2& ~0x33)>>2 | (w2&0x33)<<2);
11342 w2=combobuf[i].csets;
11343 combobuf[i].csets= (((w2& ~0x50)>>1 | (w2&0x50)<<1) & ~0x0F) | (w2 & 0x0F);
11344 }
11345
11346 redraw=true;
11347 saved=false;
11348 break;
11349
11350 case KEY_M:
11351 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
11352 {
11353 move_combos(tile,tile2,copy,copycnt);
11354 saved=false;
11355 }
11356
11357 redraw=true;
11358 break;
11359
11360 case KEY_S:
11361 tile=tile2=zc_min(tile,tile2);
11362
11363 if(copy>=0 && tile!=copy)
11364 {
11365 go_combos();
11366
11367 for(int32_t i=0; i<copycnt; i++)
11368 {
11369 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11370 }
11371
11372 saved=false;
11373 setup_combo_animations();
11374 setup_combo_animations2();
11375 }
11376
11377 redraw=true;
11378 copy=-1;
11379 break;
11380
11381 case KEY_V:
11382 if((CHECK_CTRL_CMD) && copy != -1)
11383 {
11384 if(advpaste(tile, tile2, copy))
11385 {
11386 saved=false;
11387 redraw=true;
11388 copy=-1;
11389 }
11390
11391 break;
11392 }
11393
11394 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11395
11396 if(copy==-1)
11397 {
11398 go_combos();
11399
11400 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11401 {
11402 combobuf[i].flip^=2;
11403 byte w2=combobuf[i].walk;
11404 combobuf[i].walk=(w2&0x55)<<1 | (w2& ~0x55)>>1;
11405 w2=combobuf[i].csets;
11406 combobuf[i].csets= (((w2&0x30)<<2 | (w2& ~0x30)>>2) & ~0x0F) | (w2 & 0x0F);
11407 }
11408
11409 saved=false;
11410 }
11411 else
11412 {
11413 go_combos();
11414 copy_combos(tile,tile2,copy,copycnt,masscopy);
11415 setup_combo_animations();
11416 setup_combo_animations2();
11417 saved=false;
11418 }
11419
11420 redraw=true;
11421 break;
11422 case KEY_R:
11423 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11424 {
11425 combobuf[i].flip = rotate_value(combobuf[i].flip);
11426 combobuf[i].walk = rotate_walk(combobuf[i].walk);
11427 combobuf[i].csets = rotate_cset(combobuf[i].csets);
11428 }
11429
11430 redraw=true;
11431 saved=false;
11432 break;
11433
11434 case KEY_I:
11435 {
11436 // rev.1509; Can now insert/remove all selected combos
11437 int32_t z=tile;
11438 int32_t numSelected = abs(tile-tile2) + 1;
11439 tile=zc_min(tile,tile2);
11440 tile2=MAXCOMBOS;
11441 copy = tile + numSelected; // copy=tile+1;
11442 copycnt = MAXCOMBOS-tile-numSelected; // copycnt=MAXCOMBOS-tile;
11443
11444 if(key[KEY_LSHIFT]||key[KEY_RSHIFT])
11445 {
11446 char buf[64];
11447
11448 if(numSelected>1)
11449 sprintf(buf,"Remove combos %d - %d?",tile, copy-1);
11450 else
11451 sprintf(buf,"Remove combo %d?",tile);
11452
11453 if(jwin_alert("Confirm Remove",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11454 {
11455 move_combos(tile,tile2,copy, copycnt);
11456 //don't allow the user to undo; quest combo references are incorrect -DD
11457 go_combos();
11458 redraw=true;
11459 saved=false;
11460 }
11461 }
11462 else
11463 {
11464 char buf[64];
11465
11466 if(numSelected>1)
11467 sprintf(buf,"Insert %d blank combos?",numSelected);
11468 else
11469 sprintf(buf,"Insert a blank combo?");
11470
11471 if(jwin_alert("Confirm Insert",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11472 {
11473 move_combos(copy,tile2,tile, copycnt);
11474 go_combos();
11475 redraw=true;
11476 saved=false;
11477 }
11478 }
11479
11480 copy=-1;
11481 tile2=tile=z;
11482 }
11483 break;
11484
11485 case KEY_DEL:
11486 {
11487 char buf[40];
11488
11489 if(tile==tile2)
11490 {
11491 sprintf(buf,"Delete combo %d?",tile);
11492 }
11493 else
11494 {
11495 sprintf(buf,"Delete combos %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
11496 }
11497
11498 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11499 {
11500 go_combos();
11501
11502 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11503 {
11504 clear_combo(i);
11505 }
11506
11507 tile=tile2=zc_min(tile,tile2);
11508 redraw=true;
11509 saved=false;
11510 setup_combo_animations();
11511 setup_combo_animations2();
11512 }
11513 }
11514 break;
11515 }
11516
11517 clear_keybuf();
11518 }
11519
11520 if(gui_mouse_b()&1)
11521 {
11522 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
11523 {
11524 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
11525 {
11526 done=1;
11527 }
11528 }
11529
11530 int32_t x=gui_mouse_x()-screen_xofs;
11531 int32_t y=gui_mouse_y()-screen_yofs;
11532
11533 if(y>=0 && y<(208*mul))
11534 {
11535 x=zc_min(zc_max(x,0),(320*mul)-1);
11536 int32_t t;
11537
11538 if(!combo_cols)
11539 {
11540 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
11541 }
11542 else
11543 {
11544 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11545 }
11546
11547 bound(t,0,255);
11548 t+=page<<8;
11549
11550 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
11551 {
11552 tile2=t;
11553 }
11554 else
11555 {
11556 tile=tile2=t;
11557 }
11558
11559 if(tile_clicked!=t)
11560 {
11561 dclick_status=DCLICK_NOT;
11562 }
11563 else if(dclick_status == DCLICK_AGAIN)
11564 {
11565 while(gui_mouse_b())
11566 {
11567 /* do nothing */
11568 rest(1);
11569 }
11570
11571 if(!combo_cols)
11572 {
11573 t2 = (y>>4)*COMBOS_PER_ROW + (x>>4);
11574 }
11575 else
11576 {
11577 t2 = ((x>>6)*52) + ((x>>4)&3) + ((y>>4)<<2);
11578 }
11579
11580 bound(t2,0,255);
11581 t2+=page<<8;
11582
11583 if(t2!=t)
11584 {
11585 dclick_status=DCLICK_NOT;
11586 }
11587 else
11588 {
11589 go_combos();
11590 edit_combo(tile,false,cs);
11591 redraw=true;
11592 setup_combo_animations();
11593 setup_combo_animations2();
11594 }
11595 }
11596
11597 tile_clicked=t;
11598 }
11599 else if(x>(300*mul) && !bdown)
11600 {
11601 if(y<(224*mul)+panel_yofs && page>0)
11602 {
11603 --page;
11604 redraw=true;
11605 }
11606
11607 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
11608 {
11609 ++page;
11610 redraw=true;
11611 }
11612
11613 bdown=true;
11614 }
11615
11616 if(!bdown && isinRect(x,y,(202*mul),(213*mul)+panel_yofs,(202+44)*mul,(213+21)*mul))
11617 {
11618 FONT *tf = font;
11619 font = tfont;
11620
11621 if(do_text_button((202*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Edit"))
11622 {
11623 font = tf;
11624 edit_combo(tile,false,cs);
11625 redraw=true;
11626 }
11627
11628 font = tf;
11629 }
11630 else if(!bdown && isinRect(x,y,(247*mul),(213*mul)+panel_yofs,(247+44)*mul,(213+21)*mul))
11631 {
11632 FONT *tf = font;
11633 font = tfont;
11634
11635 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
11636 {
11637 done=1;
11638 }
11639
11640 font = tf;
11641 }
11642 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11643 {
11644 FONT *tf = font;
11645 font = tfont;
11646
11647 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11648 combopage_animate = combopage_animate ? 0 : 1;
11649 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11650 redraw = true;
11651
11652 font = tf;
11653 }
11654
11655 bdown=true;
11656 }
11657
11658 bool r_click = false;
11659
11660 if(gui_mouse_b()&2 && !bdown)
11661 {
11662 int32_t x=gui_mouse_x()-screen_xofs;
11663 int32_t y=gui_mouse_y()-screen_yofs;
11664
11665 if(y>=0 && y<(208*mul))
11666 {
11667 x=zc_min(zc_max(x,0),(320*mul)-1);
11668 int32_t t;
11669
11670 if(!combo_cols)
11671 {
11672 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
11673 }
11674 else
11675 {
11676 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11677 }
11678
11679 bound(t,0,255);
11680 t+=page<<8;
11681
11682 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
11683 {
11684 tile=tile2=t;
11685 }
11686 }
11687
11688 bdown = r_click = true;
11689 f=8;
11690 }
11691
11692 REDRAW:
11693
11694 if(gui_mouse_b()==0)
11695 bdown=false;
11696
11697 if((f%8) || InvalidBG == 1)
11698 redraw = true;
11699 if(otl != tile || otl2 != tile2)
11700 {
11701 otl = tile;
11702 otl2 = tile2;
11703 redraw = true;
11704 }
11705
11706 if(redraw || combopage_animate)
11707 draw_combos(page,cs,combo_cols);
11708
11709 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11710
11711 if(f&8)
11712 {
11713 int32_t x,y;
11714
11715 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11716 {
11717 if((i>>8)==page)
11718 {
11719 int32_t t=i&255;
11720
11721 if(!combo_cols)
11722 {
11723 x=(t%COMBOS_PER_ROW)<<5;
11724 y=(t/COMBOS_PER_ROW)<<5;
11725 }
11726 else
11727 {
11728 x=((t&3) + ((t/52)<<2)) << 5;
11729 y=((t%52)>>2) << 5;
11730 }
11731
11732 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11733 }
11734 }
11735
11736 SCRFIX();
11737 }
11738
11739 ++f;
11740
11741 //Seriously? There is duplicate code for the r-click menu? -Gleeok
11742 if(r_click)
11743 {
11744 NewMenu rcmenu
11745 {
11746 { "Copy", [&]()
11747 {
11748 go_combos();
11749 copy=zc_min(tile,tile2);
11750 copycnt=abs(tile-tile2)+1;
11751 } },
11752 { "Paste", [&]()
11753 {
11754 if((CHECK_CTRL_CMD) && copy != -1)
11755 {
11756 if(advpaste(tile, tile2, copy))
11757 {
11758 saved=false;
11759 redraw=true;
11760 copy=-1;
11761 }
11762 return;
11763 }
11764
11765 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11766
11767 if(copy>-1)
11768 {
11769 go_combos();
11770 copy_combos(tile,tile2,copy,copycnt,masscopy);
11771 setup_combo_animations();
11772 setup_combo_animations2();
11773 saved=false;
11774 }
11775 } },
11776 { "Adv. Paste", [&]()
11777 {
11778 if(copy > -1)
11779 {
11780 if(advpaste(tile, tile2, copy))
11781 {
11782 saved=false;
11783 redraw=true;
11784 copy=-1;
11785 }
11786 }
11787 } },
11788 { "Swap", [&]()
11789 {
11790 tile=tile2=zc_min(tile,tile2);
11791
11792 if(copy>=0 && tile!=copy)
11793 {
11794 go_combos();
11795
11796 for(int32_t i=0; i<copycnt; i++)
11797 {
11798 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11799 }
11800
11801 saved=false;
11802 setup_combo_animations();
11803 setup_combo_animations2();
11804 }
11805 copy=-1;
11806 } },
11807 { "Delete", [&]()
11808 {
11809 string msg;
11810
11811 if(tile==tile2)
11812 msg = fmt::format("Delete combo {}?",tile);
11813 else
11814 msg = fmt::format("Delete combos {}-{}?",zc_min(tile,tile2),zc_max(tile,tile2));
11815 bool didconfirm = false;
11816 AlertDialog("Confirm Delete",msg,
11817 [&](bool ret,bool)
11818 {
11819 if(ret)
11820 didconfirm = true;
11821 }).show();
11822 if(didconfirm)
11823 {
11824 go_combos();
11825
11826 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11827 clear_combo(i);
11828
11829 tile=tile2=zc_min(tile,tile2);
11830 saved=false;
11831 }
11832 } },
11833 {},
11834 { "Edit", [&]()
11835 {
11836 go_combos();
11837 edit_combo(tile,false,cs);
11838 } },
11839 { "Insert", [&]()
11840 {
11841 int z = tile;
11842 int count = abs(tile-tile2)+1;
11843 tile = zc_min(tile,tile2);
11844 tile2 = MAXCOMBOS;
11845 copy = tile+count;
11846 copycnt = MAXCOMBOS-tile-count;
11847
11848 string msg;
11849
11850 if(count>1)
11851 msg = fmt::format("Insert combos {} - {}?"
11852 " This will offset all of the combos that follow!",tile, copy-1);
11853 else
11854 msg = fmt::format("Insert combo {}?"
11855 " This will offset all of the combos that follow!",tile);
11856
11857 bool didconfirm = false;
11858 AlertDialog("Confirm Insert",msg,
11859 [&](bool ret,bool)
11860 {
11861 if(ret)
11862 didconfirm = true;
11863 }).show();
11864 if(didconfirm)
11865 move_combos(copy, tile2, tile, copycnt);
11866 else return;
11867
11868 copy = -1;
11869 tile2 = tile = z;
11870
11871 //don't allow the user to undo; quest combo references are incorrect -DD
11872 go_combos();
11873 saved = false;
11874 } },
11875 { "Remove", [&]()
11876 {
11877 int z = tile;
11878 int count = abs(tile-tile2)+1;
11879 tile = zc_min(tile,tile2);
11880 tile2 = MAXCOMBOS;
11881 copy = tile+count;
11882 copycnt = MAXCOMBOS-tile-count;
11883
11884 string msg;
11885
11886 if(count>1)
11887 msg = fmt::format("Remove combos {} - {}?"
11888 " This will offset all of the combos that follow!",tile, copy-1);
11889 else
11890 msg = fmt::format("Remove combo {}?"
11891 " This will offset all of the combos that follow!",tile);
11892
11893 bool didconfirm = false;
11894 AlertDialog("Confirm Remove",msg,
11895 [&](bool ret,bool)
11896 {
11897 if(ret)
11898 didconfirm = true;
11899 }).show();
11900 if(didconfirm)
11901 move_combos(tile, tile2, copy, copycnt);
11902 else return;
11903
11904 copy = -1;
11905 tile2 = tile = z;
11906
11907 //don't allow the user to undo; quest combo references are incorrect -DD
11908 go_combos();
11909 saved = false;
11910 } },
11911 {},
11912 { "Locations", [&]()
11913 {
11914 int32_t z = Combo;
11915 Combo = tile;
11916 onComboLocationReport();
11917 Combo = z;
11918 } },
11919 };
11920 rcmenu.pop(window_mouse_x(),window_mouse_y());
11921 redraw = true;
11922 r_click = false;
11923 goto REDRAW;
11924 }
11925
11926 }
11927 while(!done);
11928
11929 while(gui_mouse_b())
11930 rest(1);
11931 comeback();
11932 setup_combo_animations();
11933 setup_combo_animations2();
11934 _selected_combo = tile;
11935 _selected_cset = cs;
11936 popup_zqdialog_end();
11937 return done-1;
11938 }
11939
11940 int32_t onCombos()
11941 {
11942 // reset_combo_animations();
11943 combo_screen(-1,-1);
11944 // setup_combo_animations();
11945 refresh(rALL);
11946 return D_O_K;
11947 }
11948
11949 int32_t d_ctile_proc(int32_t msg,DIALOG *d,int32_t c)
11950 {
11951 //these are here to bypass compiler warnings about unused arguments
11952 d=d;
11953 c=c;
11954
11955 if(msg==MSG_CLICK)
11956 {
11957 int32_t t=curr_combo.o_tile;
11958 int32_t f=curr_combo.flip;
11959
11960 if(select_tile(t,f,1,CSet,true,0,true))
11961 {
11962 curr_combo.tile=t;
11963 curr_combo.o_tile=t;
11964 curr_combo.flip=f;
11965 return D_REDRAW;
11966 }
11967 }
11968
11969 return D_O_K;
11970 }
11971
11972 int32_t d_combo_loader(int32_t msg,DIALOG *d,int32_t c)
11973 {
11974 //these are here to bypass compiler warnings about unused arguments
11975 c=c;
11976
11977 if(msg==MSG_DRAW)
11978 {
11979 FONT *f = get_zc_font(font_lfont_l);
11980 textprintf_ex(screen,f,d->x,d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Tile:");
11981 textprintf_ex(screen,f,d->x+((1.5)*36),d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.o_tile);
11982 textprintf_ex(screen,f,d->x,d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
11983 textprintf_ex(screen,f,d->x+((1.5)*36),d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.flip);
11984 textprintf_ex(screen,f,d->x,d->y+(36),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet2:");
11985 }
11986
11987 return D_O_K;
11988 }
11989
11990 int32_t click_d_ctile_proc()
11991 {
11992 d_ctile_proc(MSG_CLICK,NULL,0);
11993 return D_REDRAW;
11994 }
11995
11996 int32_t click_d_combo_proc();
11997
11998 const char *comboscriptdroplist(int32_t index, int32_t *list_size)
11999 {
12000 if(index<0)
12001 {
12002 *list_size = bidcomboscripts_cnt;
12003 return NULL;
12004 }
12005
12006 return bidcomboscripts[index].first.c_str();
12007 }
12008 9 ListData comboscript_list(comboscriptdroplist, &font);
12009
12010 bool call_combo_editor(int32_t);
12011 bool edit_combo(int32_t c,bool freshen,int32_t cs)
12012 {
12013 FONT* ofont = font;
12014 //CSet = cs;
12015 reset_combo_animations();
12016 reset_combo_animations2();
12017 bool edited = call_combo_editor(c);
12018 font = ofont;
12019
12020 if(freshen)
12021 {
12022 refresh(rALL);
12023 }
12024
12025 setup_combo_animations();
12026 setup_combo_animations2();
12027
12028 return edited;
12029 }
12030
12031 int32_t d_itile_proc(int32_t msg,DIALOG *d,int32_t)
12032 {
12033 switch(msg)
12034 {
12035 case MSG_CLICK:
12036 {
12037 int32_t cs = d->d2;
12038 int32_t f = 0;
12039
12040 if(select_tile(d->d1,f,1,cs,true))
12041 {
12042 int32_t ok=1;
12043
12044 if(newtilebuf[d->d1].format==tf8Bit)
12045 jwin_alert("Warning",
12046 "You have selected an 8-bit tile.",
12047 "It will not be drawn correctly",
12048 "on the file select screen.",
12049 "&OK",NULL,'o',0,get_zc_font(font_lfont));
12050
12051 return D_REDRAW;
12052 }
12053 }
12054 break;
12055
12056 case MSG_DRAW:
12057 d->w = 32+4;
12058 d->h = 32+4;
12059
12060 BITMAP *buf = create_bitmap_ex(8,16,16);
12061 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12062
12063 if(buf && bigbmp)
12064 {
12065 clear_bitmap(buf);
12066 overtile16(buf,d->d1,0,0,d->fg,0);
12067 stretch_blit(buf, bigbmp, 0,0, 16, 16, 2, 2, d->w-4, d->h-4);
12068 destroy_bitmap(buf);
12069 jwin_draw_frame(bigbmp,0, 0, d->w,d->h, FR_DEEP);
12070 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12071 destroy_bitmap(bigbmp);
12072 }
12073
12074 break;
12075 }
12076
12077 return D_O_K;
12078 }
12079
12080 static DIALOG icon_dlg[] =
12081 {
12082 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
12083 { jwin_win_proc, 70, 70, 170, 104, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Game Icons", NULL, NULL },
12084 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
12085 { d_itile_proc, 108+3, 112, 20, 20, 0, 0, 0, 0, 0, 6, NULL, NULL, NULL },
12086 { d_itile_proc, 138+3, 112, 20, 20, 0, 0, 0, 0, 0, 7, NULL, NULL, NULL },
12087 { d_itile_proc, 168+3, 112, 20, 20, 0, 0, 0, 0, 0, 8, NULL, NULL, NULL },
12088 { d_itile_proc, 198+3, 112, 20, 20, 0, 0, 0, 0, 0, 9, NULL, NULL, NULL },
12089 { jwin_button_proc, 90, 145, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12090 { jwin_button_proc, 170, 145, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12091 { jwin_text_proc, 108+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "0", NULL, NULL },
12092 { jwin_text_proc, 138+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "1", NULL, NULL },
12093 { jwin_text_proc, 168+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "2", NULL, NULL },
12094 { jwin_text_proc, 198+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "3+", NULL, NULL },
12095 { jwin_text_proc, 88, 98, 12, 9, 0, 0, 0, 0, 0, 0, (void *) "Ring:", NULL, NULL },
12096 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12097 };
12098
12099 int32_t onIcons()
12100 {
12101 PALETTE pal;
12102 // pal = RAMpal;
12103 memcpy(pal,RAMpal,sizeof(RAMpal));
12104 icon_dlg[0].dp2=get_zc_font(font_lfont);
12105
12106 for(int32_t i=0; i<4; i++)
12107 {
12108 icon_dlg[i+2].d1 = QMisc.icons[i];
12109 icon_dlg[i+2].fg = i+6;
12110 load_cset(pal, i+6, pSprite(i+spICON1));
12111 }
12112
12113 zc_set_palette(pal);
12114
12115 large_dialog(icon_dlg);
12116
12117 int32_t ret = do_zqdialog(icon_dlg,7);
12118
12119 if(ret==6)
12120 {
12121 for(int32_t i=0; i<4; i++)
12122 {
12123 if(QMisc.icons[i] != icon_dlg[i+2].d1)
12124 {
12125 QMisc.icons[i] = icon_dlg[i+2].d1;
12126 saved=false;
12127 }
12128 }
12129 }
12130
12131 zc_set_palette(RAMpal);
12132 return D_O_K;
12133 }
12134
12135 // Identical to jwin_frame_proc, but is treated differently by large_dialog()
12136 int32_t d_comboframe_proc(int32_t msg, DIALOG *d, int32_t)
12137 {
12138 if(msg == MSG_DRAW)
12139 {
12140 jwin_draw_frame(screen, d->x, d->y, d->w, d->h, d->d1);
12141 }
12142
12143 return D_O_K;
12144 }
12145
12146 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t)
12147 {
12148 switch(msg)
12149 {
12150 case MSG_CLICK:
12151 {
12152 if((d->flags&D_NOCLICK))
12153 break;
12154
12155 int32_t ret = (d->flags & D_EXIT) ? D_CLOSE : D_O_K;
12156 int32_t combo2;
12157 int32_t cs;
12158
12159 if(CHECK_ALT) //place selected cmb/cs
12160 {
12161 if(gui_mouse_b()&1)
12162 {
12163 if(!CHECK_SHIFT)
12164 d->d1 = Combo;
12165 d->fg = CSet;
12166 }
12167
12168 return ret|D_REDRAW;
12169 }
12170 else if(gui_mouse_b()&2||nextcombo_fake_click==2) //clear to 0/0
12171 {
12172 d->d1=0;
12173 d->fg=0;
12174 return ret|D_REDRAW;
12175 }
12176 else if(gui_mouse_b()&1||nextcombo_fake_click==1) //popup combo picker
12177 {
12178 combo2=d->d1;
12179 cs=d->fg;
12180
12181 if((CHECK_CTRL_CMD ? select_combo_3 : select_combo_2)(combo2, cs))
12182 {
12183 d->d1=combo2;
12184 d->fg=cs;
12185 }
12186
12187 return ret|D_REDRAW;
12188 }
12189 else return ret|D_REDRAWME;
12190 }
12191 break;
12192
12193 case MSG_DRAW:
12194 {
12195 d->w = 32;
12196 d->h = 32;
12197
12198 BITMAP *buf = create_bitmap_ex(8,16,16);
12199 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12200
12201 if(buf && bigbmp)
12202 {
12203 clear_bitmap(buf);
12204
12205 if(d->d1==-1) // Display curr_combo instead of combobuf
12206 {
12207 newcombo hold = combobuf[0];
12208 combobuf[0] = curr_combo;
12209 putcombo(buf,0,0,0,d->fg);
12210 combobuf[0] = hold;
12211 }
12212 else if(d->d1)
12213 {
12214 putcombo(buf,0,0,d->d1,d->fg);
12215 }
12216
12217 stretch_blit(buf, bigbmp, 0,0, 16, 16, 0, 0, d->w, d->h);
12218 destroy_bitmap(buf);
12219 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12220 destroy_bitmap(bigbmp);
12221 }
12222 }
12223 break;
12224 }
12225 return D_O_K;
12226 }
12227
12228 // Hey, let's have a few hundred more lines of code, why not.
12229
12230 #define MR_4BIT 0
12231 #define MR_8BIT 1
12232
12233 static byte massRecolorSrc4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12234 static byte massRecolorDest4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12235 static word massRecolor8BitCSets=0; // Which CSets are affected? One bit each.
12236
12237 static byte massRecolorSrc8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12238 static byte massRecolorDest8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12239
12240 static int32_t massRecolorDraggedColor=-1;
12241 static int32_t massRecolorCSet;
12242 static bool massRecolorIgnoreBlank=true;
12243 static byte massRecolorType=MR_4BIT;
12244
12245 // Shows the sets of colors to replace from/to.
12246 // D_CSET: Colors are 0-15 within the current CSet rather than absolute.
12247 // D_SETTABLE: Colors can be dragged and dropped onto this one.
12248 #define D_CSET D_USER
12249 #define D_SETTABLE (D_USER<<1)
12250 int32_t d_mr_cset_proc(int32_t msg, DIALOG* d, int32_t)
12251 {
12252 BITMAP* bmp=screen;
12253 int32_t colorWidth=(d->w-4)/16;
12254 byte* colors=static_cast<byte*>(d->dp);
12255
12256 switch(msg)
12257 {
12258 case MSG_DRAW:
12259 {
12260 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12261
12262 int32_t baseColor=((d->flags&D_CSET)!=0) ? massRecolorCSet*16 : 0;
12263 for(int32_t c=0; c<16; c++)
12264 {
12265 rectfill(bmp,
12266 d->x+2+c*colorWidth, d->y+2,
12267 d->x+2+((c+1)*colorWidth)-1, d->y+2+d->h-5,
12268 baseColor+colors[c]);
12269 }
12270 }
12271 break;
12272
12273 case MSG_LPRESS:
12274 {
12275 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12276
12277 if(x >= 0 && x < 16) //sanity check!
12278 {
12279 massRecolorDraggedColor=colors[x];
12280 }
12281 }
12282 break;
12283
12284 case MSG_LRELEASE: // This isn't exactly right, but it'll do...
12285 if((d->flags&D_SETTABLE)!=0 && massRecolorDraggedColor>=0)
12286 {
12287 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12288 if(x >= 0 && x < 16) //sanity check!
12289 {
12290 colors[x]=massRecolorDraggedColor;
12291 d->flags|=D_DIRTY;
12292 }
12293 }
12294 massRecolorDraggedColor=-1;
12295 break;
12296 }
12297
12298 return D_O_K;
12299 }
12300
12301 // Used for the full palette in 8-bit mode.
12302 static int32_t d_mr_palette_proc(int32_t msg, DIALOG* d, int32_t)
12303 {
12304 BITMAP* bmp=screen;
12305 int colorWidth=(d->w-4)/16;
12306 d->h = 4+(colorWidth*14);
12307 int colorHeight=colorWidth;
12308
12309 switch(msg)
12310 {
12311 case MSG_DRAW:
12312 {
12313 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12314 for(int cset=0; cset<=13; cset++)
12315 {
12316 for(int color=0; color<16; color++)
12317 {
12318 rectfill(bmp,
12319 d->x+2+color*colorWidth,
12320 d->y+2+cset*colorHeight,
12321 d->x+2+((color+1)*colorWidth)-1,
12322 d->y+2+((cset+1)*colorHeight)-1,
12323 cset*16+color);
12324 }
12325 }
12326 }
12327 break;
12328
12329 case MSG_LPRESS:
12330 {
12331 int cset=(gui_mouse_y()-(d->y+2))/colorHeight;
12332 int color=(gui_mouse_x()-(d->x+2))/colorWidth;
12333 massRecolorDraggedColor=cset*16+color;
12334 }
12335 break;
12336 }
12337
12338 return D_O_K;
12339 }
12340
12341 static DIALOG recolor_4bit_dlg[] =
12342 {
12343 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12344 { jwin_win_proc, 0, 0, 216, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12345
12346 // 1
12347 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12348 { d_mr_cset_proc, 10, 42, 196, 16, 0, 0, 0, D_CSET, 0, 0, (void *)massRecolorSrc4Bit, NULL, NULL },
12349 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12350 { d_mr_cset_proc, 10, 70, 196, 16, 0, 0, 0, D_CSET|D_SETTABLE, 0, 0, (void *)massRecolorDest4Bit, NULL, NULL },
12351
12352 // 5
12353 { jwin_text_proc, 12, 96, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Apply to which CSets in 8-bit tiles?", NULL, NULL },
12354 { jwin_check_proc, 12, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "0", NULL, NULL },
12355 { jwin_check_proc, 36, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "1", NULL, NULL },
12356 { jwin_check_proc, 60, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "2", NULL, NULL },
12357 { jwin_check_proc, 84, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "3", NULL, NULL },
12358 { jwin_check_proc, 108, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "4", NULL, NULL },
12359 { jwin_check_proc, 132, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "5", NULL, NULL },
12360 { jwin_check_proc, 156, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "6", NULL, NULL },
12361 { jwin_check_proc, 12, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "7", NULL, NULL },
12362 { jwin_check_proc, 36, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "8", NULL, NULL },
12363 { jwin_check_proc, 60, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "9", NULL, NULL },
12364 { jwin_check_proc, 84, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "10", NULL, NULL },
12365 { jwin_check_proc, 108, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "11", NULL, NULL },
12366 { jwin_check_proc, 132, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "12", NULL, NULL },
12367 { jwin_check_proc, 156, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "13", NULL, NULL },
12368
12369 // 20
12370 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12371 { jwin_func_button_proc, 14, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset4Bit },
12372 { jwin_button_proc, 82, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 8-bit mode", NULL, NULL },
12373 { jwin_button_proc, 44, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12374 { jwin_button_proc, 112, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12375
12376 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12377 };
12378
12379 #define MR4_SRC_COLORS 2
12380 #define MR4_DEST_COLORS 4
12381 #define MR4_8BIT_EFFECT_START 6
12382 #define MR4_IGNORE_BLANK 20
12383 #define MR4_RESET 21
12384 #define MR4_SWITCH 22
12385 #define MR4_OK 23
12386 #define MR4_CANCEL 24
12387
12388 static DIALOG recolor_8bit_dlg[] =
12389 {
12390 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12391 { jwin_win_proc, 0, 0, 288, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12392
12393 // 1
12394 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12395 { d_mr_cset_proc, 10, 42, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorSrc8Bit, NULL, NULL },
12396 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12397 { d_mr_cset_proc, 10, 70, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorDest8Bit, NULL, NULL },
12398 { d_mr_palette_proc, 144, 32, 132, 150, vc(15), vc(1), 0, 0, 0, 0, (void *) NULL, NULL, NULL },
12399
12400 // 6
12401 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12402 { jwin_func_button_proc, 50, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset8Bit },
12403 { jwin_button_proc, 118, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 4-bit mode", NULL, NULL },
12404 { jwin_button_proc, 80, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12405 { jwin_button_proc, 148, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12406
12407 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12408 };
12409
12410 #define MR8_SRC_COLORS 2
12411 #define MR8_DEST_COLORS 4
12412 #define MR8_PALETTE 5
12413 #define MR8_IGNORE_BLANK 6
12414 #define MR8_RESET 7
12415 #define MR8_SWITCH 8
12416 #define MR8_OK 9
12417 #define MR8_CANCEL 10
12418
12419 static void massRecolorInit(int32_t cset)
12420 {
12421 massRecolorDraggedColor=-1;
12422 massRecolorCSet=cset;
12423
12424 recolor_4bit_dlg[0].dp2=get_zc_font(font_lfont);
12425 recolor_8bit_dlg[0].dp2=get_zc_font(font_lfont);
12426
12427 for(int32_t i=0; i<=13; i++)
12428 {
12429 if((massRecolor8BitCSets&(1<<i))!=0)
12430 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags|=D_SELECTED;
12431 else
12432 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&=~D_SELECTED;
12433 }
12434
12435 if(massRecolorIgnoreBlank)
12436 {
12437 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags|=D_SELECTED;
12438 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags|=D_SELECTED;
12439 }
12440 else
12441 {
12442 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&=~D_SELECTED;
12443 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&=~D_SELECTED;
12444 }
12445
12446 large_dialog(recolor_4bit_dlg);
12447 large_dialog(recolor_8bit_dlg);
12448
12449 // Quick fix for large_dialog() screwing these up. It's ugly. Whatever.
12450 if((recolor_4bit_dlg[MR4_DEST_COLORS].w-4)%4!=0)
12451 {
12452 recolor_4bit_dlg[MR4_SRC_COLORS].x++;
12453 recolor_4bit_dlg[MR4_SRC_COLORS].w-=2;
12454 recolor_4bit_dlg[MR4_DEST_COLORS].x++;
12455 recolor_4bit_dlg[MR4_DEST_COLORS].w-=2;
12456
12457 recolor_8bit_dlg[MR8_SRC_COLORS].x++;
12458 recolor_8bit_dlg[MR8_SRC_COLORS].w-=2;
12459 recolor_8bit_dlg[MR8_DEST_COLORS].x++;
12460 recolor_8bit_dlg[MR8_DEST_COLORS].w-=2;
12461 recolor_8bit_dlg[MR8_PALETTE].x++;
12462 recolor_8bit_dlg[MR8_PALETTE].w-=2;
12463 recolor_8bit_dlg[MR8_PALETTE].y++;
12464 recolor_8bit_dlg[MR8_PALETTE].h-=2;
12465 }
12466 }
12467
12468 static void massRecolorApplyChanges()
12469 {
12470 massRecolor8BitCSets=0;
12471 for(int32_t i=0; i<=13; i++)
12472 {
12473 if((recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&D_SELECTED)!=0)
12474 massRecolor8BitCSets|=1<<i;
12475 }
12476
12477 if(massRecolorType==MR_4BIT)
12478 massRecolorIgnoreBlank=(recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&D_SELECTED)!=0;
12479 else
12480 massRecolorIgnoreBlank=(recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&D_SELECTED)!=0;
12481 }
12482
12483 static bool massRecolorSetup(int32_t cset)
12484 {
12485 massRecolorInit(cset);
12486
12487 // Remember the current colors in case the user cancels.
12488 int32_t oldDest4Bit[16], oldSrc8Bit[16], oldDest8Bit[16];
12489 for(int32_t i=0; i<16; i++)
12490 {
12491 oldDest4Bit[i]=massRecolorDest4Bit[i];
12492 oldSrc8Bit[i]=massRecolorSrc8Bit[i];
12493 oldDest8Bit[i]=massRecolorDest8Bit[i];
12494 }
12495
12496 byte type=massRecolorType;
12497 int32_t ret;
12498 do
12499 {
12500 HANDLE_CLOSE_ZQDLG();
12501 if(exiting_program) break;
12502 if(type==MR_4BIT)
12503 {
12504 ret=do_zqdialog(recolor_4bit_dlg, MR4_OK);
12505 if(ret==MR4_SWITCH)
12506 type=MR_8BIT;
12507 }
12508 else
12509 {
12510 ret=do_zqdialog(recolor_8bit_dlg, MR8_OK);
12511 if(ret==MR8_SWITCH)
12512 type=MR_4BIT;
12513 }
12514 } while(ret==MR4_SWITCH || ret==MR8_SWITCH);
12515
12516 if(ret!=MR4_OK && ret!=MR8_OK) // Canceled
12517 {
12518 for(int32_t i=0; i<16; i++)
12519 {
12520 massRecolorDest4Bit[i]=oldDest4Bit[i];
12521 massRecolorSrc8Bit[i]=oldSrc8Bit[i];
12522 massRecolorDest8Bit[i]=oldDest8Bit[i];
12523 }
12524 return false;
12525 }
12526
12527 // OK
12528 massRecolorType=type;
12529 massRecolorApplyChanges();
12530 return true;
12531 }
12532
12533 static void massRecolorApply4Bit(int32_t tile)
12534 {
12535 byte buf[256];
12536 unpack_tile(newtilebuf, tile, 0, true);
12537
12538 if(newtilebuf[tile].format==tf4Bit)
12539 {
12540 for(int32_t i=0; i<256; i++)
12541 buf[i]=massRecolorDest4Bit[unpackbuf[i]];
12542 }
12543 else // 8-bit
12544 {
12545 for(int32_t i=0; i<256; i++)
12546 {
12547 word cset=unpackbuf[i]>>4;
12548 if((massRecolor8BitCSets&(1<<cset))!=0) // Recolor this CSet?
12549 {
12550 word color=unpackbuf[i]&15;
12551 buf[i]=(cset<<4)|massRecolorDest4Bit[color];
12552 }
12553 else
12554 buf[i]=unpackbuf[i];
12555 }
12556 }
12557
12558 pack_tile(newtilebuf, buf, tile);
12559 }
12560
12561 static void massRecolorApply8Bit(int32_t tile)
12562 {
12563 byte buf[256];
12564 unpack_tile(newtilebuf, tile, 0, true);
12565
12566 for(int32_t i=0; i<256; i++)
12567 {
12568 byte color=unpackbuf[i];
12569 for(int32_t j=0; j<16; j++)
12570 {
12571 if(massRecolorSrc8Bit[j]==color)
12572 {
12573 color=massRecolorDest8Bit[j];
12574 break;
12575 }
12576 }
12577 buf[i]=color;
12578 }
12579
12580 pack_tile(newtilebuf, buf, tile);
12581 }
12582
12583 static void massRecolorApply(int32_t tile)
12584 {
12585 if(massRecolorIgnoreBlank && blank_tile_table[tile])
12586 return;
12587
12588 if(massRecolorType==MR_4BIT)
12589 massRecolorApply4Bit(tile);
12590 else // 8-bit
12591 {
12592 if(newtilebuf[tile].format==tf4Bit)
12593 return;
12594 massRecolorApply8Bit(tile);
12595 }
12596 }
12597
12598 static void massRecolorReset4Bit()
12599 {
12600 for(int32_t i=0; i<16; i++)
12601 massRecolorDest4Bit[i]=i;
12602 recolor_4bit_dlg[MR4_DEST_COLORS].flags|=D_DIRTY;
12603 }
12604
12605 static void massRecolorReset8Bit()
12606 {
12607 for(int32_t i=0; i<16; i++)
12608 {
12609 massRecolorSrc8Bit[i]=0;
12610 massRecolorDest8Bit[i]=0;
12611 }
12612
12613 recolor_8bit_dlg[MR8_SRC_COLORS].flags|=D_DIRTY;
12614 recolor_8bit_dlg[MR8_DEST_COLORS].flags|=D_DIRTY;
12615 }
12616
12617 6 void center_zq_tiles_dialogs()
12618 {
12619 6 jwin_center_dialog(create_relational_tiles_dlg);
12620 6 jwin_center_dialog(icon_dlg);
12621 6 jwin_center_dialog(leech_dlg);
12622 6 jwin_center_dialog(move_textbox_list_dlg);
12623 6 jwin_center_dialog(recolor_4bit_dlg);
12624 6 jwin_center_dialog(recolor_8bit_dlg);
12625 6 }
12626
12627 //.ZCOMBO
12628
12629 int32_t readcombo_loop(PACKFILE* f, word section_version, newcombo& temp_combo);
12630 int32_t writecombo_loop(PACKFILE *f, word section_version, newcombo const& tmp_cmb);
12631
12632 int32_t readcombofile_old(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t zversion,
12633 dword section_version, dword section_cversion, int32_t index, int32_t count)
12634 {
12635 newcombo temp_combo;
12636 for ( int32_t tilect = 0; tilect < count; tilect++ )
12637 {
12638 temp_combo.clear();
12639 if(!p_igetw(&temp_combo.tile,f))
12640 {
12641 return 0;
12642 }
12643 temp_combo.o_tile = temp_combo.tile;
12644
12645 if(!p_getc(&temp_combo.flip,f))
12646 {
12647 return 0;
12648 }
12649
12650 if(!p_getc(&temp_combo.walk,f))
12651 {
12652 return 0;
12653 }
12654
12655 if(!p_getc(&temp_combo.type,f))
12656 {
12657 return 0;
12658 }
12659
12660 if(!p_getc(&temp_combo.csets,f))
12661 {
12662 return 0;
12663 }
12664
12665 if(!p_getc(&temp_combo.frames,f))
12666 {
12667 return 0;
12668 }
12669
12670 if(!p_getc(&temp_combo.speed,f))
12671 {
12672 return 0;
12673 }
12674
12675 if(!p_igetw(&temp_combo.nextcombo,f))
12676 {
12677 return 0;
12678 }
12679
12680 if(!p_getc(&temp_combo.nextcset,f))
12681 {
12682 return 0;
12683 }
12684
12685 if(!p_getc(&temp_combo.flag,f))
12686 {
12687 return 0;
12688 }
12689
12690 if(!p_getc(&temp_combo.skipanim,f))
12691 {
12692 return 0;
12693 }
12694
12695 if(!p_igetw(&temp_combo.nexttimer,f))
12696 {
12697 return 0;
12698 }
12699
12700 if(!p_getc(&temp_combo.skipanimy,f))
12701 {
12702 return 0;
12703 }
12704
12705 if(!p_getc(&temp_combo.animflags,f))
12706 {
12707 return 0;
12708 }
12709
12710 //2.55 starts here
12711 if ( zversion >= 0x255 )
12712 {
12713 if ( section_version >= 12 )
12714 {
12715 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12716 {
12717 if(!p_igetl(&temp_combo.attributes[q],f))
12718 {
12719 return 0;
12720 }
12721 }
12722 if(!p_igetl(&temp_combo.usrflags,f))
12723 {
12724 return 0;
12725 }
12726 for ( int32_t q = 0; q < 3; q++ )
12727 {
12728 if(!p_igetl(&temp_combo.triggerflags[q],f))
12729 {
12730 return 0;
12731 }
12732 }
12733
12734 if(!p_igetl(&temp_combo.triggerlevel,f))
12735 {
12736 return 0;
12737 }
12738 if(section_version >= 22)
12739 {
12740 if(!p_getc(&temp_combo.triggerbtn,f))
12741 {
12742 return 0;
12743 }
12744 }
12745 if(section_version < 23)
12746 {
12747 switch(temp_combo.type) //combotriggerCMBTYPEFX now required for combotype-specific effects
12748 {
12749 case cSCRIPT1: case cSCRIPT2: case cSCRIPT3: case cSCRIPT4: case cSCRIPT5:
12750 case cSCRIPT6: case cSCRIPT7: case cSCRIPT8: case cSCRIPT9: case cSCRIPT10:
12751 case cTRIGGERGENERIC: case cCSWITCH:
12752 temp_combo.triggerflags[0] |= combotriggerCMBTYPEFX;
12753 }
12754 }
12755 if(section_version >= 24)
12756 {
12757 if(!p_getc(&temp_combo.triggeritem,f))
12758 {
12759 return 0;
12760 }
12761 if(!p_getc(&temp_combo.trigtimer,f))
12762 {
12763 return 0;
12764 }
12765 }
12766 if(section_version >= 25)
12767 {
12768 if(!p_getc(&temp_combo.trigsfx,f))
12769 {
12770 return 0;
12771 }
12772 }
12773 else
12774 {
12775 switch(temp_combo.type)
12776 {
12777 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
12778 if(!(temp_combo.usrflags & cflag3))
12779 temp_combo.attribytes[3] = WAV_DOOR;
12780 temp_combo.usrflags &= ~cflag3;
12781 break;
12782 }
12783 }
12784 if(section_version < 26)
12785 {
12786 if(temp_combo.type == cARMOS)
12787 {
12788 if(temp_combo.usrflags & cflag1)
12789 temp_combo.usrflags |= cflag3;
12790 }
12791 }
12792 if(section_version >= 27)
12793 {
12794 if(!p_igetl(&temp_combo.trigchange,f))
12795 {
12796 return qe_invalid;
12797 }
12798 }
12799 else
12800 {
12801 if(temp_combo.triggerflags[0] & 0x00040000) //'next'
12802 temp_combo.trigchange = 1;
12803 else if(temp_combo.triggerflags[0] & 0x00080000) //'prev'
12804 temp_combo.trigchange = -1;
12805 else temp_combo.trigchange = 0;
12806 temp_combo.triggerflags[0] &= ~(0x00040000|0x00080000);
12807 }
12808 if(section_version >= 29)
12809 {
12810 if(!p_igetw(&temp_combo.trigprox,f))
12811 {
12812 return qe_invalid;
12813 }
12814 if(!p_getc(&temp_combo.trigctr,f))
12815 {
12816 return qe_invalid;
12817 }
12818 if(!p_igetl(&temp_combo.trigctramnt,f))
12819 {
12820 return qe_invalid;
12821 }
12822 }
12823 else
12824 {
12825 temp_combo.trigprox = 0;
12826 temp_combo.trigctr = 0;
12827 temp_combo.trigctramnt = 0;
12828 }
12829 if(section_version >= 30)
12830 {
12831 if(!p_getc(&temp_combo.triglbeam,f))
12832 {
12833 return qe_invalid;
12834 }
12835 }
12836 else temp_combo.triglbeam = 0;
12837 if(section_version >= 31)
12838 {
12839 if(!p_getc(&temp_combo.trigcschange,f))
12840 {
12841 return qe_invalid;
12842 }
12843 if(!p_igetw(&temp_combo.spawnitem,f))
12844 {
12845 return qe_invalid;
12846 }
12847 if(!p_igetw(&temp_combo.spawnenemy,f))
12848 {
12849 return qe_invalid;
12850 }
12851 if(!p_getc(&temp_combo.exstate,f))
12852 {
12853 return qe_invalid;
12854 }
12855 if(!p_igetl(&temp_combo.spawnip,f))
12856 {
12857 return qe_invalid;
12858 }
12859 if(!p_getc(&temp_combo.trigcopycat,f))
12860 {
12861 return qe_invalid;
12862 }
12863 }
12864 else
12865 {
12866 temp_combo.trigcschange = 0;
12867 temp_combo.spawnitem = 0;
12868 temp_combo.spawnenemy = 0;
12869 temp_combo.exstate = -1;
12870 temp_combo.spawnip = 0;
12871 temp_combo.trigcopycat = 0;
12872 }
12873 if(section_version >= 32)
12874 {
12875 if(!p_getc(&temp_combo.trigcooldown,f))
12876 {
12877 return qe_invalid;
12878 }
12879 }
12880 else
12881 {
12882 temp_combo.trigcooldown = 0;
12883 }
12884 char label[12];
12885 label[11] = '\0';
12886 for ( int32_t q = 0; q < 11; q++ )
12887 {
12888 if(!p_getc(&label[q],f))
12889 {
12890 return 0;
12891 }
12892 }
12893 temp_combo.label = label;
12894 }
12895 if ( section_version >= 13 )
12896 {
12897 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12898 {
12899 if(!p_getc(&temp_combo.attribytes[q],f))
12900 {
12901 return 0;
12902 }
12903 }
12904
12905 }
12906 }
12907
12908 if ( !(skip && (index+(tilect-1)) < skip) ) //is -1 still needed here?
12909 {
12910 if ( !nooverwrite || combobuf[index+tilect].is_blank() )
12911 {
12912 combobuf[index+(tilect)] = temp_combo;
12913 }
12914 }
12915 }
12916
12917 return 1;
12918 }
12919
12920 int32_t readcombofile(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t start)
12921 {
12922 dword section_version=0;
12923 dword section_cversion=0;
12924 int32_t zversion = 0;
12925 int32_t zbuild = 0;
12926
12927 if(!p_igetl(&zversion,f))
12928 {
12929 return 0;
12930 }
12931 if(!p_igetl(&zbuild,f))
12932 {
12933 return 0;
12934 }
12935 if(!p_igetw(&section_version,f))
12936 {
12937 return 0;
12938 }
12939 if(!p_igetw(&section_cversion,f))
12940 {
12941 return 0;
12942 }
12943
12944 if ( zversion > ZELDA_VERSION )
12945 {
12946 al_trace("Cannot read .zcombo packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
12947 return 0;
12948 }
12949
12950 else if ( ( section_version > V_COMBOS ) || ( section_version == V_COMBOS && section_cversion > CV_COMBOS ) )
12951 {
12952 al_trace("Cannot read .zcombo packfile made using V_COMBOS (%d) subversion (%d)\n", section_version, section_cversion);
12953 return 0;
12954
12955 }
12956 else
12957 {
12958 al_trace("Reading a .zcombo packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
12959 }
12960
12961 int32_t index = 0;
12962 int32_t count = 0;
12963
12964 //tile id
12965 if(!p_igetl(&index,f))
12966 {
12967 return 0;
12968 }
12969 if(start > -1) index = start;
12970 // al_trace("Reading combo: index(%d)\n", index);
12971
12972 //tile count
12973 if(!p_igetl(&count,f))
12974 {
12975 return 0;
12976 }
12977 // al_trace("Reading combo: count(%d)\n", count);
12978 reset_combo_animations();
12979 reset_combo_animations2();
12980
12981 if(section_version < 33)
12982 return readcombofile_old(f,skip,nooverwrite,zversion,section_version,section_cversion,index,count);
12983
12984 newcombo temp_combo;
12985 size_t end = index+count;
12986 for ( size_t q = index; q < end; q++ )
12987 {
12988 auto ret = readcombo_loop(f,section_version,temp_combo);
12989 if(ret) return 0;
12990
12991 if ( !(skip && q-1 < skip) )
12992 {
12993 if ( !nooverwrite || combobuf[q].is_blank() )
12994 {
12995 combobuf[q] = temp_combo;
12996 }
12997 }
12998 }
12999
13000 return 1;
13001 }
13002 int32_t readcombofile_to_location(PACKFILE *f, int32_t start, byte nooverwrite, int32_t skip)
13003 {
13004 return readcombofile(f,skip,nooverwrite,start);
13005 }
13006 int32_t writecombofile(PACKFILE *f, int32_t index, int32_t count)
13007 {
13008 dword section_version=V_COMBOS;
13009 dword section_cversion=CV_COMBOS;
13010 int32_t zversion = ZELDA_VERSION;
13011 int32_t zbuild = VERSION_BUILD;
13012
13013 if(!p_iputl(zversion,f))
13014 {
13015 return 0;
13016 }
13017 if(!p_iputl(zbuild,f))
13018 {
13019 return 0;
13020 }
13021 if(!p_iputw(section_version,f))
13022 {
13023 return 0;
13024 }
13025
13026 if(!p_iputw(section_cversion,f))
13027 {
13028 return 0;
13029 }
13030
13031 //start tile id
13032 if(!p_iputl(index,f))
13033 {
13034 return 0;
13035 }
13036
13037 //count
13038 if(!p_iputl(count,f))
13039 {
13040 return 0;
13041 }
13042 reset_combo_animations();
13043 reset_combo_animations2();
13044 size_t end = index+count;
13045 for(size_t q = index; q < end; ++q)
13046 {
13047 if(writecombo_loop(f, section_version, combobuf[q]))
13048 return 0;
13049 }
13050
13051 return 1;
13052
13053 }
13054
13055 //.ZALIAS
13056
13057
13058 //.ZALIAS
13059
13060 int32_t readcomboaliasfile(PACKFILE *f)
13061 {
13062 dword section_version=0;
13063 dword section_cversion=0;
13064 int32_t zversion = 0;
13065 int32_t zbuild = 0;
13066 word tempword = 0;
13067
13068 if(!p_igetl(&zversion,f))
13069 {
13070 return 0;
13071 }
13072 if(!p_igetl(&zbuild,f))
13073 {
13074 return 0;
13075 }
13076 if(!p_igetw(&section_version,f))
13077 {
13078 return 0;
13079 }
13080 if(!p_igetw(&section_cversion,f))
13081 {
13082 return 0;
13083 }
13084 al_trace("readoneweapon section_version: %d\n", section_version);
13085 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
13086
13087 if ( zversion > ZELDA_VERSION )
13088 {
13089 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13090 return 0;
13091 }
13092
13093 else if ( ( section_version > V_COMBOALIASES ) || ( section_version == V_COMBOALIASES && section_cversion > CV_COMBOALIASES ) )
13094 {
13095 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d) subversion (%d)\n", section_version, section_cversion);
13096 return 0;
13097
13098 }
13099 else
13100 {
13101 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13102 }
13103
13104 int32_t index = 0;
13105 int32_t count = 0;
13106 int32_t count2 = 0;
13107 byte tempcset = 0;
13108
13109 //tile id
13110 if(!p_igetl(&index,f))
13111 {
13112 return 0;
13113 }
13114 al_trace("Reading combo: index(%d)\n", index);
13115
13116 //tile count
13117 if(!p_igetl(&count,f))
13118 {
13119 return 0;
13120 }
13121 al_trace("Reading combo: count(%d)\n", count);
13122
13123 combo_alias temp_alias;
13124 memset(&temp_alias, 0, sizeof(temp_alias));
13125
13126 for ( int32_t tilect = 0; tilect < count; tilect++ )
13127 {
13128 memset(&temp_alias, 0, sizeof(temp_alias));
13129 if(!p_igetw(&temp_alias.combo,f))
13130 {
13131 return 0;
13132 }
13133
13134 if(!p_getc(&temp_alias.cset,f))
13135 {
13136 return 0;
13137 }
13138
13139
13140
13141 if(!p_igetl(&count2,f))
13142 {
13143 return 0;
13144 }
13145 al_trace("Read, Combo alias count is: %d\n", count2);
13146 if(!p_getc(&temp_alias.width,f))
13147 {
13148 return 0;
13149 }
13150
13151 if(!p_getc(&temp_alias.height,f))
13152 {
13153 return 0;
13154 }
13155
13156 if(!p_getc(&temp_alias.layermask,f))
13157 {
13158 return 0;
13159 }
13160 //These values are flexible, and may differ in size, so we delete them
13161 //and recreate them at the correct size on the pointer.
13162 temp_alias.combos.clear();
13163 temp_alias.csets.clear();
13164 for(int32_t k=0; k<count2; k++)
13165 {
13166 if(!p_igetw(&tempword,f))
13167 {
13168 //al_trace("Could not reas alias.combos[%d]\n",k);
13169 return 0;
13170 }
13171 else
13172 {
13173 //al_trace("Read Combo Alias Combo [%d] as: %d\n", k, tempword);
13174
13175
13176 //al_trace("tempword is: %d\n", tempword);
13177 temp_alias.combos[k] = tempword;
13178 //al_trace("Combo Alias Combo [%d] is: %d\n", k, temp_alias.combos[k]);
13179 }
13180 }
13181 //al_trace("Read alias combos.\n");
13182
13183 for(int32_t k=0; k<count2; k++)
13184 {
13185 if(!p_getc(&tempcset,f))
13186 //if(!p_getc(&temp_alias.csets[k],f))
13187 {
13188 return 0;
13189 }
13190 else
13191 {
13192 //al_trace("Read Combo Alias CSet [%d] as: %d\n", k, tempcset);
13193
13194 temp_alias.csets[k] = tempcset;
13195 //al_trace("Combo Alias CSet [%d] is: %d\n", k, temp_alias.csets[k]);
13196 }
13197 }
13198 //al_trace("Read alias csets.\n");
13199 //al_trace("About to memcpy a combo alias\n");
13200 memcpy(&combo_aliases[index+(tilect)],&temp_alias,sizeof(combo_alias));
13201 }
13202
13203 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
13204
13205
13206 return 1;
13207
13208 }
13209
13210 int32_t readcomboaliasfile_to_location(PACKFILE *f, int32_t start)
13211 {
13212 dword section_version=0;
13213 dword section_cversion=0;
13214 int32_t zversion = 0;
13215 int32_t zbuild = 0;
13216
13217 if(!p_igetl(&zversion,f))
13218 {
13219 return 0;
13220 }
13221 if(!p_igetl(&zbuild,f))
13222 {
13223 return 0;
13224 }
13225 if(!p_igetw(&section_version,f))
13226 {
13227 return 0;
13228 }
13229 if(!p_igetw(&section_cversion,f))
13230 {
13231 return 0;
13232 }
13233 al_trace("readcomboaliasfile_to_location section_version: %d\n", section_version);
13234 al_trace("readcomboaliasfile_to_location section_cversion: %d\n", section_cversion);
13235
13236 if ( zversion > ZELDA_VERSION )
13237 {
13238 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13239 return 0;
13240 }
13241 else if ( ( section_version > V_COMBOALIASES ) || ( section_version == V_COMBOALIASES && section_cversion > CV_COMBOALIASES ) )
13242 {
13243 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d) subversion (%d)\n", section_version, section_cversion);
13244 return 0;
13245
13246 }
13247 else
13248 {
13249 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13250 }
13251
13252 int32_t index = 0;
13253 int32_t count = 0;
13254 int32_t count2 = 0;
13255 byte tempcset = 0;
13256 word tempword = 0;
13257
13258
13259 //tile id
13260 if(!p_igetl(&index,f))
13261 {
13262 return 0;
13263 }
13264 al_trace("Reading tile: index(%d)\n", index);
13265
13266 //tile count
13267 if(!p_igetl(&count,f))
13268 {
13269 return 0;
13270 }
13271 al_trace("Reading tile: count(%d)\n", count);
13272
13273
13274 combo_alias temp_alias;
13275 memset(&temp_alias, 0, sizeof(temp_alias));
13276
13277 for ( int32_t tilect = 0; tilect < count; tilect++ )
13278 {
13279 memset(&temp_alias, 0, sizeof(temp_alias));
13280 if(!p_igetw(&temp_alias.combo,f))
13281 {
13282 return 0;
13283 }
13284
13285 if(!p_getc(&temp_alias.cset,f))
13286 {
13287 return 0;
13288 }
13289
13290 int32_t count2 = 0;
13291
13292 if(!p_igetl(&count2,f))
13293 {
13294 return 0;
13295 }
13296
13297 if(!p_getc(&temp_alias.width,f))
13298 {
13299 return 0;
13300 }
13301
13302 if(!p_getc(&temp_alias.height,f))
13303 {
13304 return 0;
13305 }
13306
13307 if(!p_getc(&temp_alias.layermask,f))
13308 {
13309 return 0;
13310 }
13311 //These values are flexible, and may differ in size, so we delete them
13312 //and recreate them at the correct size on the pointer.
13313 temp_alias.combos.clear();
13314 temp_alias.csets.clear();
13315
13316 for(int32_t k=0; k<count2; k++)
13317 {
13318 if(!p_igetw(&tempword,f))
13319 {
13320 return 0;
13321 }
13322 else
13323 {
13324 temp_alias.combos[k] = tempword;
13325 }
13326 }
13327
13328 for(int32_t k=0; k<count2; k++)
13329 {
13330 if(!p_getc(&tempcset,f))
13331 {
13332 return 0;
13333 }
13334 else
13335 {
13336 temp_alias.csets[k] = tempcset;
13337 }
13338 }
13339
13340 if ( start+(tilect) < MAXCOMBOALIASES )
13341 {
13342 memcpy(&combo_aliases[start+(tilect)],&temp_alias,sizeof(temp_alias));
13343 }
13344 }
13345 return 1;
13346 }
13347 int32_t writecomboaliasfile(PACKFILE *f, int32_t index, int32_t count)
13348 {
13349 al_trace("Running writecomboaliasfile\n");
13350 dword section_version=V_COMBOALIASES;
13351 dword section_cversion=CV_COMBOALIASES;
13352 int32_t zversion = ZELDA_VERSION;
13353 int32_t zbuild = VERSION_BUILD;
13354
13355 if(!p_iputl(zversion,f))
13356 {
13357 return 0;
13358 }
13359 if(!p_iputl(zbuild,f))
13360 {
13361 return 0;
13362 }
13363 if(!p_iputw(section_version,f))
13364 {
13365 return 0;
13366 }
13367
13368 if(!p_iputw(section_cversion,f))
13369 {
13370 return 0;
13371 }
13372
13373 //start tile id
13374 if(!p_iputl(index,f))
13375 {
13376 return 0;
13377 }
13378
13379 //count
13380 if(!p_iputl(count,f))
13381 {
13382 return 0;
13383 }
13384
13385 for ( int32_t tilect = 0; tilect < count; tilect++ )
13386 {
13387
13388 if(!p_iputw(combo_aliases[index+(tilect)].combo,f))
13389 {
13390 return 0;
13391 }
13392
13393 if(!p_putc(combo_aliases[index+(tilect)].cset,f))
13394 {
13395 return 0;
13396 }
13397
13398 int32_t count2 = ((combo_aliases[index+(tilect)].width+1)*(combo_aliases[index+(tilect)].height+1))*(comboa_lmasktotal(combo_aliases[index+(tilect)].layermask)+1);
13399
13400 if(!p_iputl(count2,f))
13401 {
13402 return 0;
13403 }
13404 al_trace("Write`, Combo alias count is: %d\n", count2);
13405
13406 if(!p_putc(combo_aliases[index+(tilect)].width,f))
13407 {
13408 return 0;
13409 }
13410
13411 if(!p_putc(combo_aliases[index+(tilect)].height,f))
13412 {
13413 return 0;
13414 }
13415
13416 if(!p_putc(combo_aliases[index+(tilect)].layermask,f))
13417 {
13418 return 0;
13419 }
13420
13421 for(int32_t k=0; k<count2; k++)
13422 {
13423 if(!p_iputw(combo_aliases[index+(tilect)].combos[k],f))
13424 {
13425 return 0;
13426 }
13427 }
13428
13429 for(int32_t k=0; k<count2; k++)
13430 {
13431 if(!p_putc(combo_aliases[index+(tilect)].csets[k],f))
13432 {
13433 return 0;
13434 }
13435 }
13436 }
13437
13438 return 1;
13439
13440 }
13441